Sich verändernde Variablen in tkinter darstellen

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Ich hab schon die nächste Frage.

    Mit tkinter habe ich ein Fenster erstellt, dass die von einem Arduino gesendete Werte darstellt. Soweit funktioniert das auch.

    Jetzt versuche ich die sich ständig verändernden Variablen irgendwie zu aktualisieren. Ich habe mich an after() versucht und mir auch Multithreading angesehen.

    Beide Methoden haben nicht das gewünschte Ergebnis geliefert.

    Wenn ich das Erzeugen der GUI in meine While true Schleife schreibe, hängt das Programm solange bis ich das Fenster schließe. Dann wird ein neues Fenster mit aktuellen Werten erzeugt.

    Schreibe ich die GUI außerhalb wird sie logischerweise nie erstellt.

    Kann mir jemand erklären wie ich eine Live-Anzeige meiner Werte hinbekomme?

  • Hallo,

    Zitat

    Ich habe mich an after() versucht und mir auch Multithreading angesehen.

    Beide Methoden haben nicht das gewünschte Ergebnis geliefert.

    Die `after`Methode it die richtige Wahl. "haben nicht das gewünschte Ergebnis" geliefert ist jetzt aber auch kein Hinweis, aus dem man irgendeinen Tipp ableiten kann -> zeig' deinen Code.

    `while True` Schleifen in einer GUI sind nie eine gute Idee, weil die den Mainloopm der GUI blockieren.

    Gruß, noisefloor

  • So ich hab mal versucht meinen Code auf das Wesentliche runter zu brechen:

    Wenn ich den Code ausführe, öffnet sich das Fenster mit den Werten. Wenn ich das Fenster über das Kreuz oben rechts schließe, öffnet sich ein neues Fenster mit aktualisierten Werten. Ich habe auch versucht, die GUI außerhalb der Schleife zu schreiben aber dann wird die gar nicht erst geöffnet.
    Ich hab auch schon versucht die Datenabfrage und die GUI in eigene Funktionen zu schreiben, um dann mit Multithreading ran zu gehen, da verstehe ich aber keine der Anleitungen die ich gefunden habe.

  • Moin,

    eine GUI wird einmal definiert und dann aktiviert. Was Du da machst , ist das ständige Erzeugen / Aktivieren der GUI.

    Leider wie so oft , einfach kopiert und zusammengeschustert.

    Mein genereller Vorschlag : Immer Programmablaufplan erstellen.

    Bis Zeile 25 sieht es gut aus: Schnittstelle suchen, final öffnen

    Dann aber: kein try oder while. Sondern GUI definieren und aktivieren (die Zeilen 43 bis 55)

    Das Auslesen der Schnittstelle gehört in eine eigene Funktion, welche über ".after " zyklisch von der GUI aufgerufen wird. Das ".after" kann z.B. an eines der Anzeige-Label gebunden werden oder aber an das Hauptfenster. Letzteres sieht eleganter aus.

    Also vor window.mainloop() die Auslesefunktion starten, window.after(10,Auslesefunktion)

    Auslesefunktion steht dabei für den freigewählten Namen der Funktion. 10 steht für 10 Millisekunden, ist nur ein Beispielwert.

    Die letzte, immer durchlaufene Zeile in der Auslesefunktion muss nochmals window.after(10,Auslesefunktion) enthalten, damit der Prozeß immer wiederholt wird. Programmsteuerungsmassnahmen, damit nicht ein letzter Aufruf der Funktion nach dem Schließen des Hauptfensters ins Leere geht, kann man über die Methode .after_cancel() bei Programmende bewerkstelligen.

    Die Aktualisierung der Label , also das Anzeigen der Messwerte , erfolgt auch aus dieser Funktion. Die Methode heißt ".set" z.B. für die Temperaturanzeige namens "temp" . temp.set ("Die Temperatur beträgt: " + str(Temp) + " Grad Celsius")

    Die Funktion des Auslesens muss im Quelltext VOR die GUI-Definition gesetzt werden.

    Fertigen Code gibt es leider nicht, ich hoffe aber, genug Anregungen geliefert zu haben.

  • Hallo,

    grundsätzlich: alles außer mega-trviale GUI gehören in eine Klasse. Alles andere ist nicht wart- und erweiterbar. Ein Beispiele für eine klassenbasierte Tkinter GUI findest du in der Python Doku.

    String werden bei Python nicht mit + zusammengestückelt, dafür gibt es die `format`-Methode von Strings oder ab Python 3.6 f-Strings.

    Nie nackte try-except verwenden, weil du damit _alle_ Fehler abfängst, auch Programmierfehler. Fehler immer gezielt abfangen, also z.B. `except ConnectionError:`.

    `while 1` ist unpythonisch, besser ist `while True`. Die Klammern in Zeile 38 und 39 sind überflüssig.

    Variablennamen schreibt man per Konvention klein. Also `ph`, `temp` usw. Außerdem sollten Variablenname _aussagekräftig_ sein. `string` ist als ein ziemlich schlechter Variablenname.

    Konstanten werden per Konvention in GROSSBUCHSTABEN geschrieben. PORT und DEVICE sind aber nicht wirklich konstant bei dir.

    PORT und DEVICE sind identisch - warum? BAUD wird 2x definiert, das ist 1x zu viel.

    Wenn du das Hauptfenster der GUI schließen willst rufst du dessen `destroy` Methode auf. `sys.exit()` ist suboptimal. Würde in deinem Code übrigens auch nicht funktionieren, weil du `sys` nicht importierst.

    Du importierst tkinter 2x, in zwei verschiedene Namensräume. Das ist 1x zu viel. *-Importe möchte man normalerweise nicht nutzen, weil man sich damit den globalen Namensraum zumüllst.

    Gruß, noisefloor

  • Vielen Dank für die hilfreichen Tipps!

    Habe eine andere Lösung gefunden.
    Die GUI wird außerhalb der Schleife initialisiert und innerhalb werden lediglich meine Labels über update() aktualisiert.

    Funktioniert bis jetzt sehr gut.

    Werde mich aber drum bemühen mein Programm nochmal zu überarbeiten und unnötige Programmteile entfernen.

    Gruß, Luise

  • Hallo,

    Zitat

    Funktioniert bis jetzt sehr gut.

    Gut - aber kann eigentlich nicht klasse-basiert implementiert sind. Klingt eher so, als würdest du den globalen Namensraum und ggf. `global` benutzen - was suboptimal ist.

    Kannst bei Gelegenheit ja nochmal den aktualisierten Code zeigen.

    "Funktioniert" und "guter / robuster Code" ist halt nicht das gleiche.

    Gruß, noisefloor

Jetzt mitmachen!

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