Laufende Uhrzeit im Label-widget

Fragen zu Tkinter.
Antworten
Bungler
User
Beiträge: 2
Registriert: Freitag 1. Juli 2022, 13:24

Hallo liebes Forum.

Ich möchte auf einem Label-Widget die Laufende Uhrzeit mit strftime angezeigt bekommen. Aber leider läuft die Zeit im Label nicht weiter sondern verharrt beim Anfangswert.

Allerdings läuft die uhrzeit() NACH dem hauptfenster.mainloop in der python-konsole weiter wie es auch beim Label oben sein sollte.

Wo steckt der Fehler.

Bitte keine Beispiele mit class !
OOP-Programmierung verstehe ich nicht , weil mir zu hoch !

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
from time import strftime, sleep
import tkinter

hauptfenster = tkinter.Tk()
hauptfenster.geometry("400x200")
hauptfenster.title("Bunglers Wecker")
hauptfenster.minsize(width=400, height=200)
hauptfenster.maxsize(width=400, height=200)

akt_zeit = tkinter.StringVar()


def uhrzeit():
    z = 1
    while z == 1:
        akt_zeit.set(strftime('%H:%M:%S'))
        return akt_zeit.get()
        time.sleep(1)

etikett_1 = tkinter.Label(hauptfenster, text=uhrzeit(),  bg="green", font="arial 20 bold")
etikett_1.place(x=100, y=70, width=200, height=40)

hauptfenster.mainloop()


def uhrzeit():
    z = 1
    while z == 1:
        akt_zeit.set(strftime('%H:%M:%S'))
        print(akt_zeit.get())
        time.sleep(1)

uhrzeit()

__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ein Murmeltierthem. Wird hier bestaendig diskutiert. Dazu braucht es Timer, und die erreicht man mit after in tkinter. Einfach mal (via google) hier im Forum suchen.

Und GUI ohne OOP geht nicht auf Dauer. Dann ist das auch zu hoch 🤷‍♂️
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Für GUIs braucht man Klassen, anders geht es nicht, falls Dir das zu hoch ist, dann sind GUIs für Dich noch zu hoch und das sollte Dir Ansporn sein, das zu lernen.
Man benutzt keine globalen Variablen, sondern alles was eine Funktion braucht, muß sie über ihre Argumente bekommen, und der Code außerhalb von Funktionen muß auch in eine Funktion, die man üblicherweise main nennt.
`z` auf 1 zu setzen und dann diesen Wert mit 1 zu vergleichen ist ziemlich klar, was das für ein Ergebnis gibt: True, und daher sollte man auch einfach eine while-True-Schleife benutzen. Was man aber bei GUIs nicht machen darf, wie __deets__ ja schon geschireben hat.
Deine while-Schleife ist aber gar keine Schleife, weil Du sie sofort per `return` wieder verläßt.
Du benutzt ein StringVar-Objekt, aber übergibst dessen Wert fix als text=-Argument an Dein Label; das macht den Nutzen von StringVar-Objekten zunichte.

Irgendwelche Zahlen an Variablennamen zu heften, macht man auch nicht, warum nicht etikett_543?
place benutzt man nicht und die Größe des Fensters gibt man auch nicht vor, weil das die Programme auf anderen Systemen unter Umständen unbrauchbar macht.
Bungler
User
Beiträge: 2
Registriert: Freitag 1. Juli 2022, 13:24

OK. Danke erst mal. So komme ich also wahrhaftig nicht um OOP herum.
Von Basic her bin ich es ja gewohnt das der Code der Reihe nach abgearbeitet wird. Mit sprüngen zu Unterprogrammen und zurück. Diese Denkweise ist wohl bei OOP nicht angebracht.

Aber wie muß ich mir dann denn Programmablauf vorstellen ?
Ich habe mir ein Lernvideo von https://www.youtube.com/watch?v=tVNsC6tDJu8 angeschaut und nun meinen Code ich eine Klasse gepackt.

Mein Tkinter-Fenster öffnet sich auch wie erhofft aber leider zeigt das Label nur eine unveränderliche Zeit an. Nach meinem Verständnis müßte doch durch mainloop() alle Code-Abschnitte in der Klasse von oben nach unten
immer wieder abgearbeitet werden und bei jedem Loop-Durchlauf auch immer wieder die Zeit neu geladen und angezeigt werden.

Code: Alles auswählen

import tkinter
import time
from time import strftime, sleep



class Fenster:

    def __init__(self):
        self.hauptfenster = tkinter.Tk()
        self.akt_zeit = tkinter.StringVar()


        self.akt_zeit.set(strftime('%H:%M:%S'))


        self.hauptfenster.geometry("400x200")

        self.hauptfenster.title("Bunglers Wecker")

        self.etikett = tkinter.Label(self.hauptfenster, text=self.akt_zeit.get(),  bg="green", font="arial 20 bold")

        self.etikett.place(x=100, y=70, width=200, height=40)

        self.hauptfenster.mainloop()



instanz = Fenster()

Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Nein, das Problem bei GUIs ist, dass sie auf Events reagieren, und man deshalb keinen Linearen Programmfluss mehr hat. Das hat im ersten Moment nichts mit OOP zu tun.
Was Du gemacht hast, ist eine einfache Funktion kompliziert als Klasse zu schreiben. Damit ist nichts gewonnen.
Du mußt per `after` regelmäßig eine Funktion aufrufen, um die Anzeige zu aktualisieren.
Die StringVar-Instanz benutzt Du immer noch falsch, `sleep` wird importiert, aber zum Glück nicht verwendet, weil man das eh nicht gebrauchen kann.

Code: Alles auswählen

import tkinter
from time import strftime

class Fenster:
    def __init__(self):
        self.hauptfenster = tkinter.Tk()
        self.akt_zeit = tkinter.StringVar(self.hauptfenster, strftime('%H:%M:%S'))
        self.hauptfenster.title("Bunglers Wecker")
        tkinter.Label(self.hauptfenster, textvariable=self.akt_zeit,
            bg="green", font="arial 20 bold").pack()
        self.hauptfenster.after(1000, self.update)

    def mainloop(self):
        self.hauptfenster.mainloop()

    def update(self):
        self.hauptfenster.after(1000, self.update)
        self.akt_zeit.set(strftime('%H:%M:%S'))


def main():
    fenster = Fenster()
    fenster.mainloop()

if __name__ == "__main__":
    main()
Antworten