Seite 1 von 1

Python/Tkinter Label-foreground dynamisch ändern

Verfasst: Donnerstag 11. August 2016, 14:42
von ribby
Hallo Forum,
dies ist mein erster Post - bitte insoweit um Nachsicht !
Ich möchte über ein Python-Skript auf einem Raspberry Sensordaten einer Solarthermieanlage aus einer Datei iterierend einzulesen und graphisch darzustellen. Dabei bin ich auf ein tkinter-Skript gestossen, dass ich für meinen Zweck angepasst habe und das aktuell bis auf einen letzten Punkt lauffähig ist:

Die Ausgabezeile für den Pumspenstatus soll je nach Inhalt des Textfeldes (AN oder AUS) in verschiedenen Farben (grün / rot) dargestellt werden. Ich habe unterschiedlichste Dinge erfolglos probiert - mir fehlen einfach die Basiskenntnisse in Python / Tkinter und nicht zuletzt bin ich auch in OO noch nicht sehr bewandert. Hier das Skript:

Code: Alles auswählen

#!/usr/local/bin/python
# coding: latin-1 
import Tkinter as tk

COL_PUMP="white"
EINHEIT = " °C "
COL_FOR = "yellow"
COL_BACK= "black"
FONT1="Helvetica 70 bold"
FONT2="Helvetica 55 bold"

LOG_FILE = "/home/pi/dlogg/UVR31-last.log"
 
class MainWin(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.attributes("-fullscreen", True)

        self.configure(background=COL_BACK)
        self.kollektor = tk.StringVar()
        self.speicherOben = tk.StringVar()
        self.speicherUnten = tk.StringVar()
        self.pumpe = tk.StringVar()
        self.pumpcol = tk.StringVar()
        self.datum = tk.StringVar()
        self.uhrzeit = tk.StringVar()
        self.zeitpunkt = tk.StringVar()

	tk.Label(self, text="Solaranlagenstatus", fg=COL_FOR, bg=COL_BACK, font=FONT1).grid(row=0,column=0)

        tk.Label(self, text="Kollektor:          ", fg=COL_FOR, bg=COL_BACK, font=FONT2).grid(row=1,column=0)
        tk.Label(self, textvariable=self.kollektor, fg=COL_FOR, bg=COL_BACK, font=FONT2).grid(row=1,column=1)

        tk.Label(self, text="Speicher oben: ",fg=COL_FOR, bg=COL_BACK, font=FONT2).grid(row=2,column=0)
        tk.Label(self, textvariable=self.speicherOben, fg=COL_FOR, bg=COL_BACK, font=FONT2).grid(row=2,column=1)

        tk.Label(self, text="Speicher unten:",fg=COL_FOR, bg=COL_BACK, font=FONT2).grid(row=3,column=0)
        tk.Label(self, textvariable=self.speicherUnten, fg=COL_FOR, bg=COL_BACK, font=FONT2).grid(row=3,column=1)

	tk.Label(self, text="    Pumpe:                  ",fg=COL_FOR,bg=COL_BACK, font=FONT2).grid(row=4,column=0)        
        p = tk.Label(self, textvariable=self.pumpe, fg=COL_PUMP, bg=COL_BACK, font=FONT2) 
        p.grid(row=4,column=1) 
        
        if self.pumpe.get() == "AN":
        	p.configure(fg="green")
        else:
		p.configure(fg="red")
	
        tk.Label(self, text="    Uhrzeit:                  ", fg=COL_FOR, bg=COL_BACK, font=FONT2).grid(row=5,column=0)
        tk.Label(self, textvariable=self.uhrzeit,fg=COL_FOR, bg=COL_BACK, font=FONT2).grid(row=5,column=1)

        tk.Label(self, text="    Datum:                   ", fg=COL_FOR, bg=COL_BACK, font=FONT2).grid(row=6,column=0)
        tk.Label(self, textvariable=self.datum,fg=COL_FOR, bg=COL_BACK, font=FONT2).grid(row=6,column=1)

	tk.Button (self, text='Exit', fg=COL_FOR, bg=COL_BACK, font="Helvetica 20 bold",command=self.quit).grid(row=14,column=1
)

        self.after(1000, self.read)
       
    def read(self):
        with open(LOG_FILE) as lines:
            for line in lines:
			pass
            self.datum.set(line.rstrip()[8:10] + '.' + line.rstrip()[5:7] + '.' + line.rstrip()[0:4])
            self.uhrzeit.set(line.rstrip()[11:20])
            self.zeitpunkt.set(self.uhrzeit.get() + ' / ' + self.datum.get())
            self.kollektor.set(line.rstrip()[30:35] + '  °C ')
       	    self.speicherUnten.set(line.rstrip()[40:45] + '  °C ')
            self.speicherOben.set(line.rstrip()[50:55] + '  °C ')
            self.pumpe.set(line.rstrip()[59:60])
	    if self.pumpe.get() == "0" :
		self.pumpe.set("AUS")	
	    if self.pumpe.get() == "1" :
		self.pumpe.set("AN")	

        self.after(1000, self.read)

def main():
    root = MainWin()
    root.mainloop()
 
if __name__ == '__main__':
    main()
Die If-Abfrage in der MainWin-Klasse stellt das dar, was ich beabsichtigt habe, aber trotz fehlerfreiem syntax-Check nicht wirksam ist.

Wäre toll, wenn mir jemand helfen könnte, den "letzten Schliff" hinzukriegen.

Viele Grüße
Jürgen

Re: Python/Tkinter Label-foreground dynamisch ändern

Verfasst: Samstag 13. August 2016, 23:14
von kaytec
Hallo Jürgen,
gibt es in lines nur ein Element oder benötigst du das letzte Element ? Mache aus der Variable p einfach self.p.

Code: Alles auswählen

if self.pumpe.get() == "AN":
    self.p.configure(fg="green")
else:
     self.p.configure(fg="red")
Dies so ändern und in die Funktion read einfügen. Danach sollte es die Farbe ändern.

Gruß Frank

Re: Python/Tkinter Label-foreground dynamisch ändern

Verfasst: Sonntag 14. August 2016, 11:02
von ribby
Hallo Frank,

danke für den Vorschlag - er bringt aber leider noch nicht den gewünschten Effekt. Nach der Änderung erhalte ich die folgende Fehlermeldung:

Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1437, in __call__
return self.func(*args)
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 498, in callit
func(*args)
File "/home/pi/dlogg/sol-disp.py", line 77, in read
self.p.configure(fg="red")
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1791, in __getattr__
return getattr(self.tk, attr)
AttributeError: p

Falls Du das Skript selber testen möchtest, hier ein Musterdatensatz (die Datei enthält immer nur einen - den aktuellen - Satz):

2016-08-14_11:59:29 UVR31 S1: 60.3 S2: 48.1 S3: 52.5 A: 1

In diesem Beispiel läuft die Pumpe, der Wert "AN" sollte also grün erscheinen.

Viele Grüße
Jürgen

Re: Python/Tkinter Label-foreground dynamisch ändern

Verfasst: Sonntag 14. August 2016, 11:43
von Sirius3
@ribby: Du hast den ersten Satz von kaytec überlesen: »Mache aus der Variable p einfach self.p.« Mit anderen Worten: binde das Label aus __init__ an ein Attribut ›p‹ oder besser ›pump_label‹, so dass Du es in ›read‹ benutzen kannst. Statt die Log-Zeile per magischer Indexwerte anzusprechen solltest Du einen kleinen Parser dafür schreiben. Das ist lesbarer und die Chance ist größer, dass es auch weiterhin funktioniert, wenn sich am Format leicht etwas ändert (z.B. ein S4 oder Temperaturen über 100°C)

Code: Alles auswählen

import Tkinter as tk
from datetime import datetime as Datetime
import re

[...]

class MainWin(tk.Tk):
    def __init__(self):
        [...]
        self.pump_label = p
        self.after(1000, self.read)

    def read(self):
        with open(LOG_FILE) as lines:
            for line in lines:
                pass
        datum, _, daten = line.split(None, 2)
        datum = DateTime.strptime(datum, '%Y-%m-%d_%H:%M:%S')
        daten = dict(re.findall(r'(\w+):\s*(\S+)', daten))
        self.datum.set('%d.%m.%Y'.format(datum))
        self.uhrzeit.set('%H:%M:%S'.format(datum))
        self.zeitpunkt.set('%H:%M:%S / %d.%m.%Y'.format(datum))
        self.kollektor.set('{[S1]} °C'.format(daten))
        self.speicherUnten.set('{[S2]} °C'.format(daten))
        self.speicherOben.set('{[S3]} °C'.format(daten))
        pumpe_an = daten['A'] != '0'
        self.pumpe.set('AN' if pumpe_an else 'AUS')
        self.pump_label['fg'] = 'green' if pumpe_an else 'red'
        self.after(1000, self.read)

Re: Python/Tkinter Label-foreground dynamisch ändern

Verfasst: Sonntag 21. August 2016, 20:55
von ribby
funktioniert jetzt perfekt !!!

Vielen Dank Euch Beiden (auch für die sonstigen sinnvollen Verbesserungsvorschläge).

Viele Grüße
Jürgen