Ausgabe in einfaches Fenster

Fragen zu Tkinter.
Antworten
Herbie
User
Beiträge: 2
Registriert: Mittwoch 5. August 2020, 15:43

Hallo zusammen - ich bin neu im Forum und neu in Python - das untenstehende Programm liest die serielle Schnitstelle aus - der Wert "rpm" beinhaltet die Drehzahl eines Motors. Der Drehzahlsensor liefert serielle Werte ab die ich mit meinem Raspberry Pi auswerten will. Jetzt hätte ich gern ein kleines Fenster das mir die Drehzahl anzeigt. Ich habe mich mal schlau gemacht und ein paar Tutorials gelesen - bin aber letztendlich steckengeblieben :( :( :(
Das Programm in seiner jetzigen Form zeigt ein kleines Fenster an - der Rest unterhalb "root.mainloop" wird aber nicht mehr ausgeführt. Wenn ich root.mainloop an das Programmende stelle wird zwar der Code ausgeführt und die Drehzahlwerte werden in der Konsole angezeigt aber es erscheint kein Fenster mehr!! Wie mache ich es das sowohl das Fenster angezeigt wird als auch das der restliche Code ausgeführt wird?
Wie übergebe ich die Variable "rpm" an "myLabel = Label(root, ) sodass ihr Wert (Drehzahl) im Fenster angezeigt wird? Für ein paar gute Tips wäre ich wirklich dankbar!!!!!
#!/usr/bin/env python

import serial
from tkinter import *

root = Tk()
myLabel = Label(root, text = "Test Test Test")
myLabel.pack()
root.mainloop()


ser = serial.Serial(port='/dev/ttyAMA0', baudrate = 9600, timeout=1)
if (ser.isOpen() == True):
ser.close()
ser.open()

try:
while 1:
rpm = ser.readline().rstrip()
print (rpm)
ser.write(rpm)

except(KeyboardInterrupt, SystemExit):
print("Abbruch")
ser.close()
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Warum fangen Neulinge immer mit dem schwierigsten an. Vergiss einmal GUIs. Das ist sehr kompliziert, wenn das was im Hintergrund passieren soll. Da braucht es Threads und Queues und after. Alles Dinge die hier im Forum schon hunderte Male besprochen wurden.
`ser` ist immer eine offene Verbindung. Nur weil einer mal gedacht hast "oh, das gibt es eine Methode isOpen, die muss ich unbedingt benutzen" wird es immer und immer wieder kopiert, das Internet ist doof. Da wünscht man sich ein globales Suchen-und-Ersetzen.
Noch doofer ist es, ser dann gleich wieder zu schließen und zu öffnen. Was soll denn das bringen? Die Klammern um die if-Bedingung sind überflüssig und kommen weg. Explizit auf True braucht man auch nicht prüfen. Später benutzt du 1 statt True. Hier würde man auch einfach eine for-Schleife über die Zeilen von ser schreiben. SystemExit sollte man nicht anfangen. Das close gehört in einen finally-Block, besser wäre es aber Du benutzt with.

Code: Alles auswählen

#!/usr/bin/env python3
import serial
with ser = serial.Serial(port='/dev/ttyAMA0', baudrate=9600, timeout=1):
    for line in ser:
        rpm = line.rstrip()
        print(rpm)
Benutzeravatar
sparrow
User
Beiträge: 4193
Registriert: Freitag 17. April 2009, 10:28

@Herbie: Um dein "Problem" kurz aufzuklären:

Jedes mir bekannte GUI-Framework benutzt eine eigene Schleife um dafür zu sorgen, dass die Oberfläche auch "gezeichnet" wird. Dies Schleife (bei tkinter der "mainloop") darf nicht - oder wenn dann nur kurz - unterbrochen werden, weil sonst die Oberfläche einfriert. Kennst du das bei Windows, wenn ein Programm "nicht reagiert" und Windows anbietet es abzuschießen oder zu warten? Da ist eben jene Schleife unterbrochen.

Deshalb wird auch nie ausgeführt, was du nach dem Aufruf von mainloop schreibst. Da kommt das Programm nicht an, während die Oberfläche läuft.

Es gibt also leider kein "einfaches Fenster". GUI-Programmierung ist nicht trivial und erfordert ein komplettes Umdenken, denn dann wird Code in der Hauptschleife nicht mehr einfach sequentiell ausgeführt sondern von Events (Ereignissen) ausgelöst.

Wenn man, wie du, etwas tun möchte, was potentiell endlos läuft, dann kann man das auch nicht einfach in der Hauptschleife des Programms tun, denn dann würde deine Schleife potentiell nie verlassen werden und die Oberfläche wird nie aktualisiert. Daher sind die von Sirius3 erwähnten, nicht trivialen, Werkzeuge nötig, damit das funktioniert.


Ergänzend zu den Anmerkungen von Sirius3:
Benutze keine *-Importe. Damit holst du dir - gerade bei tkinter - hunderte Namen in deinen Namensraum. Benutze stattdessen das übliche

Code: Alles auswählen

import tkinter as tk
und greife via tk. auf die Funktionen und Klassen des Moduls zu.
Benutzeravatar
__blackjack__
User
Beiträge: 13111
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Noch eine Ergänzung: Wenn man eine Zeitüberschreitung bei `Serial` setzt, sollte der Code das eventuell auch berücksichtigen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Herbie
User
Beiträge: 2
Registriert: Mittwoch 5. August 2020, 15:43

Okay...das mit der Grafik vergessen wir lieber!!!! :D :D :D
Antworten