GUI Label Werte aktualisieren

Fragen zu Tkinter.
Antworten
Kevin214
User
Beiträge: 4
Registriert: Samstag 6. April 2019, 05:45

Grüße,

Ich lasse mir Werte aus einer SPS in einer GUI anzeigen. Leider werden die Werte, die mir angezeigt werden, nicht aktualisiert.
Ich habe hier schon viel über die "While True" Schleife innerhalb eines Tkinter Programmes gelesen, aber ich kann mir leider nichts aus den vielen codes zusammen addieren das funktioniert.
Wichtig ist mir auch, dass das Programm überschaubar bleibt und es für meine Kollegen, die fast nichts mit python am Hut haben, relativ verständlich bleibt.


Villeicht kann mir jemand von euch auf die Sprünge helfen oder einen Lösungsvorschlag geben...
auch wenn euch das Thema eventuell schon nervt, wäre ich euch sehr dankbar dafür :D

Code: Alles auswählen

# -*- coding: utf-8 -*- 
from time import sleep
import time
import snap7
from snap7 import util
from snap7.util import *
import struct
from Tkinter import *


root = Tk()
root.title("Übersicht Auftrag")
root.geometry("2000x1200")
	
					
plc = snap7.client.Client()
plc.connect("192.168.0.1", 0, 2)
con = plc.get_connected()
print ("---PLC connected: "), con
data_all = plc.db_read(db_number=21, start=0, size=226)
data1 = util.get_int(data, 0)
data2 = util.get_dword(data, 64)
data3 = util.get_dword(data, 72)	


Label(root, 
			text='Auftrag Sollzahl:= ' + str (data2) +  'stk.',
			font = "Verdana 40 bold").pack()
Label(root, 
			text='Auftrag Istzahl:= ' + str (data3) +  'stk.',
			font = "Verdana 40 bold").pack()
			
Label(root, 
			text='Taktzahl:= ' + str (data1) +  'stk.',
			font = "Verdana 40 bold").pack()


root.mainloop()



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

Erstens kein Python2 mehr benutzen, das ist veraltet.
Zweitens, keine *-Importe.
Drittens, struct, time und time.sleep werden importiert aber gar nicht benutzt. ebenso nichts, was Du per `from snap7.utils import *` importierst.
Viertens, `data` ist nirgends definiert. `data123` sind auch zu generische Namen, Du weißt doch konkret, was die Zahlen bedeuten.

Um etwas zu aktualisieren, muß man das explizit machen, die statischen Texte in den Labels ändern sich nicht auf magische Art und Weise.

Das ganze in Python3.7:

Code: Alles auswählen

import tkinter as tk
import snap7
from snap7 import util

def update(labels, plc):
    data = plc.db_read(db_number=21, start=0, size=226)
    taktzahl = util.get_int(data, 0)
    sollzahl = util.get_dword(data, 64)
    istzahl = util.get_dword(data, 72)
    labels[0]['text'] = f"Auftrag Sollzahl:= {sollzahl}stk."	
    labels[1]['text'] = f"Auftrag Istzahl:= {istzahl}stk."	
    labels[2]['text'] = f"Auftrag Taktzahl:= {taktzahl}stk."
    labels[0].after(1000, update, labels, plc)

def main():
    root = tk.Tk()
    root.title("Übersicht Auftrag")
    root.geometry("2000x1200")
    plc = snap7.client.Client()
    plc.connect("192.168.0.1", 0, 2)
    labels = [
        tk.Label(root, font="Verdana 40 bold")
        for _ in range(3)
    ]
    for label in labels:
        label.pack()
    update(labels, plc)
    root.mainloop()

if __name__ == '__main__':
    main()
Kevin214
User
Beiträge: 4
Registriert: Samstag 6. April 2019, 05:45

Hallo,

Vielen Dank für den Code :)
Leider kommt bei:

labels[0] ['text'] = f"Auftrag Sollzahl:= {sollzahl}stk."

die Fehlermeldung:

SyntaxError: invalid syntax

Woran könnte es liegen?

Und kannst du mir eventuell noch verraten wie bzw wo genau im Code ich die Labels an sich programmieren kann?
Angenommen ich möchte die Labels unterschiedlich groß und an unterschiedlichen Stellen im Bild haben?

Schonmal ein großes Dankeschön im Vorraus :D
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

Wie schon geschrieben, mein Beispiel ist für Python3.7.
Kevin214
User
Beiträge: 4
Registriert: Samstag 6. April 2019, 05:45

okay, aber ich Habe im Terminal eingegeben:

python3 Dateiname.py

dürfte doch dann mit Python3.x bearbeitet werden?
__deets__
User
Beiträge: 14536
Registriert: Mittwoch 14. Oktober 2015, 14:29

3.x. — f-strings gibt es erst ab 3.6.
Kevin214
User
Beiträge: 4
Registriert: Samstag 6. April 2019, 05:45

Ja habe ich auch mitbekommen.
Dachte eigentlich das ich das neuste update habe...
Wäre cool wenn mir nochmal jemand kurz erklären könnte wie ich die Labels unterschiedlich groß und an verschiedenen Positionen bringen kann.

Habe es jetzt folgendermaßen programmiert:

Code: Alles auswählen

#!/usr/bin/env python3
import tkinter as tk
import snap7
from snap7 import util

def update(labels, plc):
    data = plc.db_read(db_number=21, start=0, size=226)
    taktzahl = util.get_int(data, 0)
    sollzahl = util.get_dword(data, 64)
    istzahl = util.get_dword(data, 68)
    labels[0]['text'] = "Auftrag Sollzahl: = " + str(sollzahl) + " stk."	
    labels[1]['text'] = "Auftrag Istzahl: = " + str(istzahl) + "stk."	
    labels[2]['text'] = "Auftrag Taktzahl: = " + str(taktzahl) + "stk."
    labels[0].after(100, update, labels, plc)

def main():
    root = tk.Tk()
    root.title("Übersicht Auftrag")
    root.geometry("2000x1200")
    plc = snap7.client.Client()
    plc.connect("192.168.0.1", 0, 2)
    labels = [
        tk.Label(root, font="Verdana 40 bold")
        for labels in range(3)
    ]
    for label in labels:
        label.pack()
    update(labels, plc)
    root.mainloop()

if __name__ == '__main__':
    main()

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

Statt `f"Auftrag Sollzahl:= {sollzahl}stk."` kann man in älteren Versionen

Code: Alles auswählen

"Auftrag Sollzahl:= {}stk.".format(sollzahl)
schreiben.

Schriftgröße gibst Du doch schon an, und wie Du die Labels positionieren willst, davon hängt ab, wie man das am besten macht.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi Kevin214

Hier mein Tipp für eine GUI-Darstellung:

Code: Alles auswählen

#!/usr/bin/env python3
import tkinter as tk
import random
#import snap7
#from snap7 import util

from functools import partial

import tkinter as tk

APP_TITLE = "Snap7 Display"
APP_XPOS = 100
APP_YPOS = 100
APP_WIDTH = 2000 #2000
APP_HEIGHT = 1200 #1200


class Application(object):
    LABELS = ["Auftrag Sollzahl", "Auftrag Istzahl", "Auftrag Taktzahl"]
    LABEL_FONT = "Verdana 40 bold"
    VALUE_LABEL_WIDTH = 6


    def __init__(self, main_win):
        self.main_win = main_win
        
        self.label_vars = list()
        self.build()
        self.display_test_loop()
        
    def build(self):
        main_frame = tk.Frame(self.main_win)
        main_frame.pack(fill='both', expand=True)

        label_frame = tk.Frame( main_frame)
        label_frame.pack(expand=True)
        
        name_label_width = 0
        for label in self.LABELS:
            if len(label) > name_label_width:
                name_label_width = len(label)

        for index, label in enumerate(self.LABELS):
            tk.Label(label_frame, font=self.LABEL_FONT, bg='gray60', fg='white',
                text="{}:".format(label), width=name_label_width, anchor='e',
                padx=20
                ).grid(row=index, column=0, pady=6)
            var = tk.StringVar(self.main_win, 0)
            tk.Label(label_frame, font=self.LABEL_FONT, textvariable=var,
                 width=self.VALUE_LABEL_WIDTH, bg='white'
                ).grid(row=index, column=1, pady=6)
            self.label_vars.append(var)

    def display_test_loop(self):
        for index, var in enumerate(self.label_vars):
            random_value = random.randint(0, 200)
            var.set(random_value)
        self.main_win.after(500, self.display_test_loop)
            
            
def main():
    main_win = tk.Tk()
    main_win.title(APP_TITLE)
    #main_win.geometry("+{}+{}".format(APP_XPOS, APP_YPOS))
    main_win.geometry("{}x{}".format(APP_WIDTH, APP_HEIGHT))
    
    app = Application(main_win)
    
    main_win.mainloop()
 
 
if __name__ == '__main__':
    main()      
Versuche deine Snap7 Zugehörigkeiten selber zu integrieren. Viel Spass beim Studium.

Gruss wuf :-)
Take it easy Mates!
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@wuf: statt `max` nachzuprogrammieren, am besten es direkt nutzen:

Code: Alles auswählen

name_label_width = max(map(len, self.LABELS))
`label_vars` wird in `__int__` angelegt, aber erst in `build` gefüllt. Da wäre es besser `build` wegzulassen und alles gleich in __init__ zu integrieren.
ikinter wird zwei mal importiert, partial importiert aber nie benutzt.
Antworten