Countdown in Textbox

Fragen zu Tkinter.
Antworten
TheBombTuber
User
Beiträge: 48
Registriert: Samstag 9. September 2017, 15:48

Hallo Ich schreibe momentan ein Programm von Python in Tkinter um.

Nun habe ich an einer Stelle das Problem, dass ich einen CountDown in ein Textfeld schreiben möchte.

Das ganze funktioniert auch Theoretisch und ich setzte es mit folgendem Code um.

Code: Alles auswählen

        def Bereinigung():
            Logfile1.write("********** Logentry " + str(datetime.now().strftime("%d-%m-%Y %H-%M-%S")) + " **********\n")
            for i in range(10,0,-1):
                Text1.insert('end',"Die Clientbereinigung startet in " + str(i)+' ' + "Sekunden\nUm die Bereinigung abzubrechen drücken Sie STRG+C\n")
                Text1.after(1000, Text1.delete(1.0, 'end'))
Das einzige Problem ist, dass mir der Text nicht angezeigt wird. Das Programm wartet 10 Sekunden und zeigt mir dann eine leere Textbox an.

Wie muss ich die after Funktion einbringen damit mir erst der Text angezeigt wird und dann die Textbox gecleart wird?

So sieht der abschnitt in meinem Konsolen Programm aus

Code: Alles auswählen

def groß_entry():
    os.system("cls")
    Logfile.write("********** Logentry " + str(datetime.now().strftime("%d-%m-%Y %H-%M-%S")) + " **********\n")
    for i in range(10,0,-1):
        sys.stdout.write("Die Clientbereinigung startet in " + str(i)+' ' + "Sekunden\nUm die Bereinigung abzubrechen drücken Sie STRG+C")
        time.sleep(1)
        sys.stdout.flush()
        os.system("cls"))
__deets__
User
Beiträge: 14536
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du hast after nicht richtig eingesetzt. after muss als Argument etwas aufrufbares bekommen. Du gibst die Rueckgabe von Text1.delete(...) an. Das ist wohl None. Da passiert also nix.

Und selbst WENN du etwas da angegeben haettest (zB ein lambda zum loeschen), dann waere das nicht das gewuenschte Ergebnis - die inserts passieren ja alle nacheinander.

Da du keine Klassen zu verwenden scheinst, wird es etwas fummelig, so etwas vernuenftig zu machen. Eine Moeglichkeit ist ein Generator. Ungetestet:

Code: Alles auswählen

def bereinigung():
      def countdown_generator(times=10):
            for i in range(times, 0, -1):
                Text1.insert('end',"Die Clientbereinigung startet in " + str(i)+' ' + "Sekunden\nUm die Bereinigung abzubrechen drücken Sie STRG+C\n") 
                 yield
             Text1.delete(1.0, 'end')
    countdown = countdown_generator()
    def schedule():
           try:
                    next(countdown)
                    Text1.after(1000, schedule)
           except StopIteration:
                     pass
      schedule()
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@TheBombTuber: So funktioniert GUI-Programmierung nicht. Du darfst keine lang laufenden Schleifen haben, denn solange die laufen wird die GUI blockiert und Änderungen werden nicht angezeigt und die GUI reagiert nicht auf den Benutzer.

`after()` ist schon die richtige Idee, aber funktioniert so nicht. Als zweites Argument erwartet die Methode etwas aufrufbares was nach der im ersten Argument angegebenen Zeit von der GUI-Hauptschleife aufgerufen wird. Du machst dort aber einen `delete()`-Aufruf *gleich* und als zweites Argument für `after() wird der *Rückgabewert* von diesem Aufruf übergeben. Der dürfte `None` sein, beziehungsweise auf keinen etwas aufrufbares was hier irgendwie Sinn machen würde. Die ``for``-Schleife geht halt so nicht. Du musst eine Funktion oder Methode haben, die alle nötigen Werte als Argumente bekommt, oder über im Fall einer Methode über das Objekt zugreifen kann.

`after()` und Countdowns sollten hier im Forum mehr als einmal zu finden sein.

IMHO ist es sinnvoll das man objektorientierte Programmierung (OOP) halbwegs drauf hat, bevor man sich an GUI-Programmierung wagt. Sonst muss man beides parallel lernen, denn OOP braucht man für jede nicht-triviale GUI.

Deine Namenschreibweise hält sich nicht an die Konventionen (Style Guide for Python Code) und die Nummerierung sollte da auch nicht sein.

Das `Bereinigung()` so weit eingerück ist, aber kein `self` als Argument bekommt, dafür aber `Logfile1` und `Text1` einfach so zu exitsieren scheinen, lässt eine lokale Funktion vermuten – das sollte aber nicht sein.

Zeichenketten und Werte mit `str()` und ``+`` zusammenstückeln ist eher BASIC als Python. In Python gibt es dafür die `format()`-Methode auf Zeichenketten und ab Python 3.6 auch f-Zeichenkettenliterale.

Mit Strg+C eine GUI-Anwendung abbrechen geht nur in einem Terminal aus dem sie gestartet wurde, falls sie denn aus eine Terminal gestartet wurde. Da würde man eher eine „Cancel“/„Abbrechen“-Schaltfläche erwarten.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
TheBombTuber
User
Beiträge: 48
Registriert: Samstag 9. September 2017, 15:48

__blackjack__ hat geschrieben: Mittwoch 19. Juni 2019, 11:36 @TheBombTuber: So funktioniert GUI-Programmierung nicht. Du darfst keine lang laufenden Schleifen haben, denn solange die laufen wird die GUI blockiert und Änderungen werden nicht angezeigt und die GUI reagiert nicht auf den Benutzer.

`after()` ist schon die richtige Idee, aber funktioniert so nicht. Als zweites Argument erwartet die Methode etwas aufrufbares was nach der im ersten Argument angegebenen Zeit von der GUI-Hauptschleife aufgerufen wird. Du machst dort aber einen `delete()`-Aufruf *gleich* und als zweites Argument für `after() wird der *Rückgabewert* von diesem Aufruf übergeben. Der dürfte `None` sein, beziehungsweise auf keinen etwas aufrufbares was hier irgendwie Sinn machen würde. Die ``for``-Schleife geht halt so nicht. Du musst eine Funktion oder Methode haben, die alle nötigen Werte als Argumente bekommt, oder über im Fall einer Methode über das Objekt zugreifen kann.

`after()` und Countdowns sollten hier im Forum mehr als einmal zu finden sein.

IMHO ist es sinnvoll das man objektorientierte Programmierung (OOP) halbwegs drauf hat, bevor man sich an GUI-Programmierung wagt. Sonst muss man beides parallel lernen, denn OOP braucht man für jede nicht-triviale GUI.

Deine Namenschreibweise hält sich nicht an die Konventionen (Style Guide for Python Code) und die Nummerierung sollte da auch nicht sein.

Das `Bereinigung()` so weit eingerück ist, aber kein `self` als Argument bekommt, dafür aber `Logfile1` und `Text1` einfach so zu exitsieren scheinen, lässt eine lokale Funktion vermuten – das sollte aber nicht sein.

Zeichenketten und Werte mit `str()` und ``+`` zusammenstückeln ist eher BASIC als Python. In Python gibt es dafür die `format()`-Methode auf Zeichenketten und ab Python 3.6 auch f-Zeichenkettenliterale.

Mit Strg+C eine GUI-Anwendung abbrechen geht nur in einem Terminal aus dem sie gestartet wurde, falls sie denn aus eine Terminal gestartet wurde. Da würde man eher eine „Cancel“/„Abbrechen“-Schaltfläche erwarten.
Ok dann werde ich mir erst einmal die OOP zu gemühte führen und anschließend ein umschreiben meines jetzigen "Konsolencodes" in Tkinter widmen.

Und auch den Styleguide werde ich mir mal durchlesen.
Antworten