Hallo zusammen,
ich "spiele" erst seit Kurzem mit Python (3.10) und meine Kenntnisse sind somit rudimentär.
Per pyserial lese ich Werte aus 2 Messgeräten aus und gebe sie per Print aus - funktioniert.
Im nächsten Schritt soll per tkinter ein GUI her, auf dem eben diese Werte angezeigt werden. Wir sprechen von 2 Spalten, also jeweils Wertepaaren.
Es muss nur angezeigt werden, daraus copy/paste wäre schick aber nicht nötig.
Frage: wie würdet ihr das am besten angehen?
- alles in z.B. Text-Widget packen?
- separates Frame mit Grid-Struktur?
- ???
Das ganze soll anfängerfreundlich aber auch funktional sein.
Freue mich auf sachdienliche Hinweise.
Danke
Klaus
Von Print zum GUI - aber wie?
Nur ein Textfeld zu benutzen, stellt ja keine echte Veränderung zum Terminal dar. Das ist auch ein Textfeld. Der simpelste Start sind Labels in einem Frame, zb vertikal oder horizontal layoutet. Grid ist auch ok. Wichtig: textvariable benutzen, damit die Werte aus der seriellen Schnittstelle in einem Hintergrundthread abgerufen und via der Variablen den Weg in den Main-Thread mit der GUI finden. Alternativ mit after arbeiten, oder createfilehandler: https://stackoverflow.com/questions/334 ... ocket-data
Ich muss nochmal um Hilfe bitten - und mich noch etwas deutlicher ausdrücken.
Das Anzeigen von ausgelesenen Werten funktioniert.
ABER: ich möchte die Werte im GUI alle angezeigt bekommen, die Liste soll also immer um die neusten Werte ergänzt werden.
Bekomme ich nicht hin, habe ein krudes Konstrukt mit konkatenierenden Strings versucht ... gruselig.
Hat jemand einen Codeschnipsel für mich an dem ich mich entlang hangeln kann?
Das Anzeigen von ausgelesenen Werten funktioniert.
ABER: ich möchte die Werte im GUI alle angezeigt bekommen, die Liste soll also immer um die neusten Werte ergänzt werden.
Bekomme ich nicht hin, habe ein krudes Konstrukt mit konkatenierenden Strings versucht ... gruselig.
Hat jemand einen Codeschnipsel für mich an dem ich mich entlang hangeln kann?
Was spricht denn gegen print?
Dann hast du auch alle Werte untereinander.
Dann hast du auch alle Werte untereinander.
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
Warum kein print? Weil zum Schluss eine .exe erzeugt werden soll, um beim Anwender keine Python-Installation nötig zu machen (und wenn das anders geht bin ich für Hinweise ebenfalls dankbar).
Folgendes Grundkonstrukt habe ich verwendet, was im Grunde ja anzeigt was ich will - nur eben nicht Zeile für Zeile wenn neue Daten reinkommen.
Folgendes Grundkonstrukt habe ich verwendet, was im Grunde ja anzeigt was ich will - nur eben nicht Zeile für Zeile wenn neue Daten reinkommen.
Code: Alles auswählen
from tkinter import *
import time
win = Tk()
# Set the geometry
win.geometry("700x350")
# Add the list of items
days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat","Sun"]
def insertText():
for day in days:
text.insert(END, day + '\n')
text = Text(win, width=80, height=15)
text.pack()
insertText()
mainloop()
Warum soll da auch was Zeile für Zeile ausgegeben werden, wenn Du alles in einer Funktion ausgibst?
*-Importe benutzt man nicht, time wird importiert, aber nicht benutzt.
Man darf keine globalen Variablen benutzen, und es sollte eine main-Funktion geben.
Die größe eines Fensters ergibt sich aus dessen Inhalt.
Variablennamen und Funktionen werden komplett klein geschrieben:
*-Importe benutzt man nicht, time wird importiert, aber nicht benutzt.
Man darf keine globalen Variablen benutzen, und es sollte eine main-Funktion geben.
Die größe eines Fensters ergibt sich aus dessen Inhalt.
Variablennamen und Funktionen werden komplett klein geschrieben:
Code: Alles auswählen
import tkinter as tk
def insert_text(text, lines):
for line in lines:
text.insert(tk.END, f'{line}\n')
def main():
win = tk.Tk()
# Add the list of items
days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat","Sun"]
text = tk.Text(win, width=80, height=15)
text.pack()
insert_text(text, days)
win.mainloop()
if __name__ == "__main__":
main()
ok, keine * Importe - Danke
time ist ein Überbleibsel
Einen Lösungsansatz sehe ich in dem verbesserten Programm nicht, es dient ja auch nur der Veranschaulichung.
Ziel: ich lese zyklisch Daten aus der seriellen Schnittstelle und will diese in einem Fenster ausgeben - so wie das vergleichsweise bei print erfolgt.
Im Beispiel sollen das die Wochentage sein die nacheinander im Text-Widget gelistet werden sollen.
time ist ein Überbleibsel
Einen Lösungsansatz sehe ich in dem verbesserten Programm nicht, es dient ja auch nur der Veranschaulichung.
Ziel: ich lese zyklisch Daten aus der seriellen Schnittstelle und will diese in einem Fenster ausgeben - so wie das vergleichsweise bei print erfolgt.
Im Beispiel sollen das die Wochentage sein die nacheinander im Text-Widget gelistet werden sollen.
Ok, ihr wollt den seriellen Part sehen. Kein Problem, aber das ist ja nicht mein Problem.
Code: Alles auswählen
import serial
import time
ser = serial.Serial('COM5', 9600)
time.sleep(5)
def read_string(channel):
command = f'ch{channel}\n'
print('Command sent: ' + command)
ser.write(command.encode('utf-8'))
time.sleep(1)
notFinish = True
while notFinish == True:
time.sleep(0.1)
nbChars = ser.inWaiting()
if nbChars > 0:
data_read = ser.read(nbChars)
notFinish = False
print('data read: ' + data_read.decode('ASCII'))
count = 0
while (count < 5):
read_string(count+1)
count +=1
time.sleep(.2)
time.sleep(.5)
ser.write(b'off\n')
ser.close()
Doch. Das ist dein Problem. Der Code funktioniert so nicht mit einer Ereignis-basierten GUI. Keine der von mir genannten Methoden zur nebenläufigen Anfrage der seriellen Schnittstelle kommt zum Einsatz. Also gehts auch nicht.
Gut - wie komm ich hier weiter?
Alleine nicht, sonst würde ich nicht fragen.
Meine Hoffnung war ein grundsätzlich funktionierendes Minimalbeispiel.
Alleine nicht, sonst würde ich nicht fragen.
Reicht mir als Hilfestellung offenbar nicht, sorry.Werte aus der seriellen Schnittstelle in einem Hintergrundthread abgerufen und via der Variablen den Weg in den Main-Thread mit der GUI finden. Alternativ mit after arbeiten, oder createfilehandler:
Meine Hoffnung war ein grundsätzlich funktionierendes Minimalbeispiel.
Das hast du bis dato halt nicht ausgedrückt. Du hast diese Hinweise bekommen, und dich dazu nicht weiter geäußert. Stattdessen war dann jetzt nur davon die Rede, dass die Darstellung funktioniert, nur irgendwas mit Konkatenierung wäre komisch. Woher soll man also wissen, wo es hakt? Erst recht ohne Code?
Jetzt ist es ein bisschen spät, um da noch was abzuliefern. Muss auf morgen warten. Der bestehende serielle Code ist übrigens großer Mist. Statt einfach blockierend mit read zu warten, wird da unnötig eine Schleife weiter getrieben. Und dann wieder künstlich mit sleep eingebremst.
Jetzt ist es ein bisschen spät, um da noch was abzuliefern. Muss auf morgen warten. Der bestehende serielle Code ist übrigens großer Mist. Statt einfach blockierend mit read zu warten, wird da unnötig eine Schleife weiter getrieben. Und dann wieder künstlich mit sleep eingebremst.
Ein einfache Methode wäre die Schnittstelle mit timeout=0 zu öffnen und dann regelmäßig per `read` alles, was bis dahin aufgelaufen ist, einzulesen und darzustellen.
Code: Alles auswählen
import tkinter as tk
import serial
def insert_text(text, ser):
text.insert(tk.END, ser.read().decode())
text.after(100, insert_text, text, ser)
def main():
win = tk.Tk()
ser = serial.Serial('COM5', 9600, timeout=0)
time.sleep(5)
ser.write(b"ch0\n")
text = tk.Text(win, width=80, height=15)
text.pack()
insert_text(text, ser)
win.mainloop()
if __name__ == "__main__":
main()
Verstehe das immer noch nicht. Das ist doch kein Grund für oder gegen print oder Tk. Beides wird ein Python-Programm sein, und beides kann zu einer .exe gepackt werden, damit der Anwender nicht nochmal einzeln Python installieren muss. (Statt dessen installiert er mehrfach Python, nämlich als Teil jeder solchen .exe aber hey )
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
Tja, offenbar hab ich einfach (noch) zu wenig Plan von dem ganzen Zeug. Aber mit lesen, probieren und eurer Hilfe wird das hoffentlich besser.
Der Code von Sirius3 funktioniert - vielen Dank dafür, werde ich so verwenden und schauen wie weit ich komme.
Der Code von Sirius3 funktioniert - vielen Dank dafür, werde ich so verwenden und schauen wie weit ich komme.