Timer innerhalb von TKinter

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo zusammen,

    ich hätte da eine Frage mit der ich mich schon seit geraumer Zeit rumschlage und zu keinem Ergebnis gekommen bin. Ich habe eine Funktion zum Messen der Temperatur innerhalb von TKinter geschrieben. Die Messung erfolgt im Hintergrund(Threading). Funktioniert bestens, allerdings soll die Funktion nicht mit einem Button, sondern automatisch innerhalb einer bestimmten Zeit immer wieder ausgeführt werden.

    Kann mir jemand sagen wie ich das in Python machen kann?


    Vielen Dank und einen guten Start ins Wochenende.

    VG whitechristmas

  • Du brauchst kein threading. Wie Manul schon sagte kannst du das problemlos über tkinter.after() abhandeln.

    Siehe dazu FAQ => Nützliche Links / Linksammlung => python: Tkinter: Im Hintergrund zählen

    Wenn noch Fragen sind dann bitte Deinen Code posten.

  • Guten Morgen,

    das Threading möchte ich beibehalten, weil die Messung bis zu mehreren Minuten andauern kann. Dann soll das Programm im Vordergrund noch reagieren. Das Timing ist von untergeordneter Bedeutung. Wenn die Wiederholung nicht exakt gestartet wird, ist das nicht schlimm.

    Ich habe das Programm ohne Klassen und nur mit Funktionen und Threading programmiert. Wie und wo muss man das after() platzieren? In dem beigefügten Link (danke dafür) istdas after() in einer Klasse verwendet.


    Vielen Dank und einen schönen Tag.

    whitechristmas

  • Du wirst aber um die Verwendung von after nicht rumkommen. Das was du da machst - messagebox.showinfo in deinem Thread-target aufrufen - funktioniert nur durch Zufall. Irgendwann schmiert dir das ab, weil gerade der main-thread und dein Hintergrundthread gleichzeitig GUI-Strukturen manipulieren.

    Wenn du das ganze nicht OO-programmieren willst (was ein Fehler ist, GUIs sind inherent OO. Sogar GTK, welches in C geschrieben ist, erfindet ein eigenes Objektmodell (GObject) um dem Mangel daran in C abzuhelfen), kannst du das natuerlich auch ueber globalen Zustand tun, indem du in messdef Statusvariablen setzt.

    Besser noch waere es aber, auf den Thread zu verzichten. Du benutzt das eh nicht mehr empfohlene os.system. Wenn du stattdessen subprocess.Popen benutzt, bekommst du ein Popen-Objekt, dessen Zustand du in einem after-Call abfragen kannst. Sobald das beendet ist, kannst du entsprechend dem returncode reagieren.

    Den code mal ausprobieren, und aus Spass im Taskmanager den sleep-Befehl waehrend der 10 Sekunden killen.

  • Leider hast du nicht das ganze Script gepostet, aber so wie es aussieht führst du ein anderes Python Script über os.system aus? Das ist eigentlich ungewöhnlich, zumal das andere Script vermutlich dann auch noch "messdateilog" als Datei erstellt? :-/
    Wieso definierst du in "messdateiextern" nicht eine Funktion um die eigentliche Messung durchzuführen und gibst dann das Messergebnis via "return" zurück, importierst diese Funktion dann in dein GUI Script und führst die Funktion dann nur noch aus? Das wäre weitaus besser/sauberer als dein kuddelmuddel über 2 Ecken ;)

    Bitte poste beide Scripts, vollständig.

  • Hallo __deets__, hallo meigrafd,

    also mit der OO-Programmierung ist so eine Sache. Ich bin lediglich Hobbyprogrammierer und bin mir eine Wetterstation am zurechtbasteln.

    Ich hab einen Teil der Messung in ein anderes Programm ausgelagert, weil ich darin ein Modul verwende, welches nur unter Python2 läuft (Temperatursensor). Die Oberfläche und die Auswertung läuft unter Pyhton 3.

    Hier ist das Skript, welches nur unter Python2 läuft und deshalb ausgelagert wurde:


    Deshalb habe ich diesen Kuddelmuddel als einzige Lösung gefunden. Ich wusste mir sonst nicht zu helfen.

    Liebe Grüße.

    whitechristmas

  • Gibts denn einen Grund wieso du die GUI über Python3 realisieren willst?
    Python3 ist nicht zwangsläufig besser als Python2. Wenn du also keinen besonderen Grund hast, bleib einfach bei python2 ;)

    Abgesehen von "tkinter.after()" gäbe es für Deinen Fall auch noch eine andere Möglichkeit, der Trick wäre dann einfach "textvariable" zu nutzen. Das siehst du zB => hier <=. Wenn du deine GUI also auf Python2 umstellst, den " humidity , temperature = Adafruit_DHT.read(sensor , pin) " Kram aus dem anderen Script in eine eigene Funktion mit Schleife pakst, kannst du mit ein bisschen tricksen die Werte in der GUI automatisch aktualisieren lassen.... Aber wie gesagt, ich kenn nicht dein GUI script

  • Hallo meigrafd,

    ich habe mich für Python3 entschieden, weil ich davon ausgegangen bin, dass Python2 über kurz oder lang ausstirbt und ich dann längerfristig was von Python3 habe. Die GUI ist eigentlich fertig und ich wollte nur noch zusehen, dass die Abfragen automatisch im Hintergrund ablaufen.


    Rechts die Werte unter "Akt. Messung" sollten sich in regelmäßigen Abständen aktualisieren.

    VG whitechristmas

  • Nein, python2 wird noch sehr lange leben und verfügbar sein. Selbst wenn es in 5 Jahren mal nicht mehr weiterentwickelt werden sollte kannst Du für deine GUI trotzdem noch python2 verwenden, installierbar wird es wohl immer sein.
    Siehe dazu auch: https://hg.python.org/peps/rev/76d43e52d978

    Zitat

    The End Of Life date (EOL, sunset date) for Python 2.7 has been moved five years into the future, to 2020. This decision was made to clarify the status of Python 2.7 and relieve worries for those users who cannot yet migrate to Python 3.


    Es gibt (wie du ja selbst gemerkt hast) noch sehr viele Module die es nur für python2 gibt, und trotzdem noch weiterentwickelt werden - und das hat gute Gründe, wieso die nicht nach python3 portiert werden, denn in den meisten Fällen ist python3 zZt langsamer und auch umständlicher


    Wie gesagt - zeig deinen Code und wir zeigen dir wie du das sinnvoll umsetzen kann - all in one Lösung ;)


    //EDIT: Bevor ichs vergesse: Die GUI sieht echt gut aus :thumbs1:

    Wie wärs wenn du einfach nur "deffresh()" mit der after Methode verwendest?
    Ungefähr so:
    [code=php]
    # Aktualisieren
    def deffresh():
    if (schieber1.get())>(schieber2.get()):
    # Startzeitpunkt liegt hinter Endzeitpunkt
    messagebox.showinfo("Bereichsauswahl ", "Der Anfangszeitpunkt liegt hinter dem Endzeitpunkt.")
    else:
    # Schieber beschriften mit Datum/Uhrzeit
    startdatum.config(text=logdatum[schieber1.get()-1])
    startuhrzeit.config(text=loguhrzeit[schieber1.get()-1][:6])
    enddatum.config(text=logdatum[schieber2.get()-1])
    enduhrzeit.config(text=loguhrzeit[schieber2.get()-1][:6])
    #logdatum.clear()
    logeinlesen()
    diagrloeschen()
    diagrerzeug()
    diagrerstellen()
    master.after(2000, deffresh)
    [/php]Damit würde sich, wenn ich das richtig sehe, die komplette Anzeige deiner GUI alle 2 Sekunden aktualisieren - die Funktion hast du ja bereits...

  • Guten Morgen Meigrafd,

    die Methode after() habe ich eingefügt. Die Funktion deffresh wird zwar alle 2 Minuten durchlaufen, aber die Messwerte werden nicht aktualisiert.

    Hast Du vielleicht eine Idee woran es liegen könnte.

    Viele Grüße und einen entspannenden Sonntag.

    whitechristmas

  • Dein "Aktualisieren" ist doch dafür gedacht die Messwerte zu aktualisieren oder nicht? Der "Aktualisieren" Button führt die Funktion "deffresh()" aus, was nun auch durch after alle 2 Sekunden ausgeführt werden müsste, so als wenn du alle 2 Sekunden deinen "Aktualisieren" Button drücken würdest...

    In dem Script was du mir gegeben hast werden die "Akt. Messung" durch eine andere Funktion behandelt: messdef()
    Diese Funktion lässt du zZt durch threading ein mal ausführen, danach nie wieder. Es fehlt also eine Schleife innerhalb der Funktion.

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!