Seite 1 von 1

Malen, wenn Fenster schon geöffnet ist

Verfasst: Freitag 20. Juli 2012, 19:00
von Zero1234
Hallo,
ich würde gerne auf mein canvas malen, nachdem ich das Fenster schon sehen kann. Mein Hauptprogramm stoppt aber nach dem erstellen des Fensters und läuft erst dann weiter, wenn ich das Fenster schließe. Kann ich das Fenster vielleicht in einem eigenen Thread aufrufen, oder gibt es andere, möglichst Anfänger gerechte wege mein Problem zu lösen?

Hauptprogramm:

Code: Alles auswählen

import zeichnen

x1=1
x2=1
y1=1
y2=1
bild = zeichnen.Leinwand(200,200)

while x1>0 and x2>0 and y1>0 and y2>0:
    x1=input()
    y1=input()
    x2=input()
    y2=input()
    bild.set_line(x1,x2,y1,y2)

In eigene Datei (zeichnen.py) ausgelagerte Klasse:

Code: Alles auswählen

from tkinter import *

class Leinwand():
    def __init__(self, canvas_width, canvas_height):
        master = Tk()
        global bild
        bild = Canvas(master,
           width=canvas_width,
           height=canvas_height)
        bild.pack()
        mainloop()

    def set_line(self, x1, y1, x2, y2):
        bild.create_line(x1, y1, x2, y2)

danke schonmal

Re: Malen, wenn Fenster schon geöffnet ist

Verfasst: Freitag 20. Juli 2012, 19:37
von BlackJack
@Zero1234: Der Aufruf der `mainloop()` kehrt erst zurück wenn das Hauptfenster zerstört wurde. Du könntest vorher eine Funktion mit der `after()`-Methode auf einem Widget zum Aufruf nach dem Anzeigen planen. Aber die sollte nicht mit `input()` blockieren, denn solange die Hauptschleife nicht läuft, wird die GUI nicht aktualisiert.

Threads sind auch keine so gute Idee weil GUI-Toolkits in der Regel nicht „thread safe” sind, das heisst man darf auch bei `tkinter` die GUI nur aus dem Thread heraus manipulieren in dem die `mainloop()` läuft.

Grundsätzlich solltest Du Dich bei GUI-Programmierung von einem linearen Programmablauf verabschieden, den *Du* komplett in der Hand hast. GUI-Programmierung bedeutet ereignisbasierte Programmierung.

Re: Malen, wenn Fenster schon geöffnet ist

Verfasst: Freitag 20. Juli 2012, 21:27
von Zero1234
Vielen danke erstmal für die Antwort.
Mein Hauptprogramm mit dem Input war auch nur um mein Problem simpel zu erklären. Eigentlich brauche ich die Ausgabe für ein Zeitkritischeres Programm, das Motoren steuert und Positionsdaten davon empfängt. Ich möchte ganz zeitunkritisch vielleicht ein Paar mal pro sekunde ein Paar neue Koordinaten auf dem Bildschirm plotten, ohne dass das die Gui mein ganzes Programm anhält. Dafür müsste ich, wenn überhaupt wohl mit einem extra Thread für die GUI arbeiten, oder?

Die einzige andere Möglichkeit die mir einfällt wäre sehr umständlich...ich könnte mein Hauptprogramm die Daten in eine Datenbak schreiben lassen und ein Programm machen, das nur für die Gui da ist und mit der after()-Methode nach einiger Zeit ein paar neue Daten aus der gleichen Datenbak ausliest. simpler wäre mir allerdings lieber.

Re: Malen, wenn Fenster schon geöffnet ist

Verfasst: Freitag 20. Juli 2012, 21:40
von BlackJack
@Zero1234: Wenn Thread dann die Arbeit dort hin verlagern und nicht die GUI und dann brauchst Du keine Datenbank sondern kannst die Threads über eine `Queue.Queue` kommunizieren lassen. Also Dein Arbeitsthread schreibt da Werte rein und bei der GUI schaust Du mit `after()` regelmässig in die Queue ob etwas zum Anzeigen vorliegt.

Re: Malen, wenn Fenster schon geöffnet ist

Verfasst: Freitag 20. Juli 2012, 22:02
von Zero1234
Vielen Dank, das klingt nach einem Plan. Werd mir die Sache mit den Threads mal ansehen.
schönen Abend noch

Re: Malen, wenn Fenster schon geöffnet ist

Verfasst: Freitag 20. Juli 2012, 22:29
von Zero1234
Ich habe mich heute erst für Tkinter entschieden, weil das zeichnen dort am einfachsten ist, aber gibt es vielleicht GUI-Toolkits, bei denen ich nicht auf Threads zurückgreifen muss? Qt zum beispiel?

Re: Malen, wenn Fenster schon geöffnet ist

Verfasst: Freitag 20. Juli 2012, 22:37
von EyDu
Nein. Wie BlackJack schon schrieb, arbeiten GUIs ereignisbasiert. BlackJack hat eigentlich auch schon genau beschrieben wie man die Aufgabe umsetzen kann.