Python/Tkinter Label-foreground dynamisch ändern

Fragen zu Tkinter.
Antworten
ribby
User
Beiträge: 3
Registriert: Donnerstag 11. August 2016, 14:15

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
Zuletzt geändert von Anonymous am Donnerstag 11. August 2016, 14:49, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

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
ribby
User
Beiträge: 3
Registriert: Donnerstag 11. August 2016, 14:15

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
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@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)
ribby
User
Beiträge: 3
Registriert: Donnerstag 11. August 2016, 14:15

funktioniert jetzt perfekt !!!

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

Viele Grüße
Jürgen
Antworten