Thread beenden bzw. Endlosschleife verlassen

Fragen zu Tkinter.
Antworten
TesterT
User
Beiträge: 4
Registriert: Dienstag 5. Oktober 2010, 18:56

Hallo liebes Forum,

seit kurzem beschäftige ich mich mit Python bzw. mit Threads.
Nun bin ich auf folgendes Problem gestossen.
Wenn ich eine GUI und einen Thread habe, die auch wunderbar kommunizieren können -
wie sorge ich beim beenden dafür, dass nicht nur die GUI sondern auch mein Thread (Endlosschleife)
geschlossen werde.

Beispiel:

Code: Alles auswählen

class Test(Thread):
    def run(self):
        i = 0
        j = 0
        while True:
            ...


    def ausstieg(self):
        ??????

class GUI(Frame):
    
    def create(self):

        self.beenden = Button(mframe)     
        self.beenden["text"] = "Beenden"
        self.beenden["command"] = self.ausstieg
        self.beenden.pack(side = RIGHT)        

    def ausstieg(self):
        root.destroy()
        test.ausstieg()       

root = Tk()
test = Test()
test.start()
widget = GUI(master = root)
root.protocol("WM_DELETE_WINDOW", widget.ausstieg)
root.mainloop()

Also, wie gesagt, die Kommunikation klappt. Ich kann nur das zweite Fenster, also meinen Thread nicht beenden.
Da wo ich die Fragezeichen eingesetzt habe ist mein Problem. Mit sys.exit(0) habe ich es schon probiert. Geht aber nicht wirklich.

Vielen Dank!

Gruss
Zuletzt geändert von TesterT am Dienstag 5. Oktober 2010, 20:52, insgesamt 2-mal geändert.
BlackJack

@TesterT: Du müsstest halt statt ``while True:`` eine Bedingung verwenden, die auch irgendwann einmal falsch werden kann. Also zum Beispiel ``while self.running:`` mit einem entsprechend initialisierten `self.running` das zum Abbrechen dann an `False` gebunden werden kann.

In `Gui.ausstieg()` solltest Du nicht auf die globalen Namen `root` und `test` zugreifen. Das ist unsauber.
TesterT
User
Beiträge: 4
Registriert: Dienstag 5. Oktober 2010, 18:56

@BlackJack: Danke für den Tipp. Wie würde denn Deiner Meinung nach so eine Inizialisierung für self.running aussehen?
Sorry, habe gerade ein Brett vor dem Kopf...

Meinst Du so...?

Code: Alles auswählen

def running(self):
     if ... :
        self.running = False
     else:
        self.running = True     



Wie bekomme ich dann aber die Verbindung zu meinem Button hin bzw. wie sollte beispielsweise mein Abbruchkriterium aussehen?

Danke und Gruss
BlackJack

@TesterT: Du kannst die Methode nicht auch `running` nennen, es kann nur ein Attribut mit dem Namen geben. Bevor die Schleife das erste mal betreten wird, muss das halt mal `True` sein, denn sonst würde der Inhalt der Schleife ja nie ausgeführt. Das würde man am ehesten in der `__init__()` machen.

Und beim Druck auf die Schaltfläche muss Code ausgeführt werden, der das Attribut dann auf `False` setzt.
patlkli
User
Beiträge: 1
Registriert: Montag 31. Mai 2010, 01:37

Um dein Beispiel zu verwenden:

Code: Alles auswählen

class Test(Thread):

    def __init__(self):
        self.is_running = False
        Thread.__init__(self)

    def run(self):
        self.is_running = True
        i = 0
        j = 0
        while self.is_running:
            i = i+1
            j = j+2

    def ausstieg(self):
        self.is_running = False

class GUI(Frame):
   
    def create(self):
        self.beenden = Button(mframe)    
        self.beenden["text"] = "Beenden"
        self.beenden["command"] = self.ausstieg
        self.beenden.pack(side = RIGHT)        

    def ausstieg(self):
        root.destroy()
        test.ausstieg()      

root = Tk()
test = Test()
test.start()
widget = GUI(master = root)
root.protocol("WM_DELETE_WINDOW", widget.ausstieg)
root.mainloop()
Die Zugriffe auf die Globals root und test innerhalb von GUI solltest du natürlich noch ändern, aber ansonsten sollte es so funktionieren.
TesterT
User
Beiträge: 4
Registriert: Dienstag 5. Oktober 2010, 18:56

Vielen Dank für Eure Antworten!!!

Meine Gedanken gingen schon in die ähnliche Richtung, aber irgendwie hat es doch
massiv an der Umsetzung gefehlt. Manchmal ist es doch gar nicht so leicht...

Gruss TesterT
Antworten