slider Widgets im Terrarium-Steuerprogramm

Fragen zu Tkinter.
Antworten
beni00
User
Beiträge: 1
Registriert: Montag 17. März 2014, 11:39

Hallo zusammen,

ich bin Anfänger und komme nicht weiter.
Den unteren Code, habe ich nach einigem Herumexperimentieren und ewigem googeln, so zum laufen gebracht, das das Programm macht was es soll:
Es misst Werte und schaltet daraufhin Relais.
Die Sollwerte, werden über Slider-Widgets gesetzt.
Die tatsächliche Werte, über Labels angezeigt.
Das alles läuft über den Raspberry pi.

Das Problem: Die Slider bleiben hängen während die Funktion def druck(ausg) (Zeile85) ausgeführt wird. dies geschieht alle 5 Sekunden. Heisst ich kann die slider 5 sekunden ohne Probleme bewegen, dann bleiben sie kurz hängen, dann kann ich sie wieder bewegen usw... . Ansich funktioniert das Programm.

Ich gehe davon aus das ich einiges falsch umgesetzt habe und dadurch der slider während der Funktion hängt.

hat jemand evtl. eine Lösung, wie ich den code umschreiben muss, damit der slider permanent flüssig läuft?
ausserdem bekomme ich es nicht hin das die Funktion schaltungen() (zeile52) permanent ausgeführt wird.
Dadurch, das ich sie, mit, in die Funktion def druck(ausg) genommen habe, wird sie auch alle 5 sek wiederholt.
Das geht aber bestimmt auch anders, leider weis ich nicht wie. :K

Bin wirklich dankbar, über Verbesserungvorschläge jeglicher Art.




Code: Alles auswählen


def temp():# Wert Temperatur
  while True:
    wert = (dht.read(11, 4 ))
    if wert != None:
        
     a,b = wert
     
     return a
         
def feuchte():# Wert Feuchtikeit
  while True:
    wert = (dht.read(11, 4 ))
    if wert != None:
        
     a,b = wert
     
     return b
     
def MeasureDistance():# Wert Wasserpegelstand

  GPIO.output(GPIOTrigger, True)


  time.sleep(0.00001)
  GPIO.output(GPIOTrigger, False)


  StartTime = time.time()
  

  while GPIO.input(GPIOEcho) == 0:
    StartTime = time.time()


  while GPIO.input(GPIOEcho) == 1:
    StopTime = time.time()


  TimeElapsed = StopTime - StartTime
  Distance = (TimeElapsed * 34300) / 2
  return round(Distance)
  
def reglerwerte(scalemintemp, scaletemp, scalefeuchte, scaleentf): # Sollwerte durch Slider-Widget
	
		a = scalemintemp.get()
		b = scaletemp.get()
		c = scalefeuchte.get()
		d = scaleentf.get()
		return (a, b, c, d)
  		
def schaltungen():# Schaltung von Relais 
	
		a = temp()
		b = feuchte()
		c = MeasureDistance()
		g,d,e,f = reglerwerte(scalemintemp, scaletemp, scalefeuchte, scaleentf)
		
		
		if d >= a:
			GPIO.output(2, True) 
		else:
			GPIO.output(2, False)
		if e >= b:
			GPIO.output(27, True)
		else:
			GPIO.output(27, False)
		if f <= c:
			GPIO.output(22, True)   
		else:
			GPIO.output(22, False)		
			
def counter_label(anzeige_temp,anzeige_feuchte,anzeige_entfernung):# anzeige werte Temperatur/Feuchtigkeit/Wasserpegelstand
  def count():
    
    a = temp()
    b = feuchte()
    c = MeasureDistance()
    anzeige_temp.config(text=(a, "C"))
    anzeige_feuchte.config(text=(b, "%"))
    anzeige_entfernung.config(text=(c, "cm"))
       
  count()

def druck(ausg):# Werte und Reglertände werden alle 5 Sekunden aktualisiert. Funktion def Schaltungen() wurde eingefügt, weil ich es nicht anders hin bekommen habe, die Funktion permanent auzuführen. -> Problem: In den 5 Sekunden Pause kann ich den Slider normal bewegen, waehrend der funktion, kann ich den slider nicht bewegen. 
	def count():
		
		
		counter_label(anzeige_temp,anzeige_feuchte,anzeige_entfernung)
		schaltungen()
		
		ausg.after(5000, count)
		
	count()
	
if __name__ == "__main__":
	
	root = tk.Tk()
	root.title("Messung")

	scalemintemp = tk.Scale(root, label="<-Heizen",from_=0, to=26)
	scalemintemp.pack(side="left")
	scalemintemp.set(18)

	anzeige_temp = tk.Label(root, fg="blue")
	anzeige_temp.pack(side="left")
	
	scaletemp = tk.Scale(root , label="<-Kuehlen:", from_=18, to=40)
	scaletemp.pack(side="left")
	scaletemp.set(23)

	anzeige_feuchte = tk.Label(root, fg="blue")
	anzeige_feuchte.pack(side="left")

	scalefeuchte = tk.Scale(root, label="<-Entfeuchten:", from_=30, to=100)
	scalefeuchte.pack(side="left")
	scalefeuchte.set(60)

	anzeige_entfernung = tk.Label(root, fg="blue")
	anzeige_entfernung.pack(side="left")

	scaleentf = tk.Scale(root, label="<-wasserstand",from_=10, to=100)
	scaleentf.pack(side="left")
	scaleentf.set(40)

	ausg = tk.Label(root, fg="blue")# Label was benutz wird damit sich die Funktion Schaltungen, wiederholt.
	ausg.pack(side="left")
	
	druck(ausg)
	root.mainloop()



BlackJack

@beni00: Auf den ersten Blick fällt auf, dass der Quelltext sehr unregelmässig formatiert ist. Konvention ist vier Leerzeichen pro Ebene beim Einrücken. Du könntest mal einen Blick in den Style Guide for Python Code werfen.

Alle 5 Sekunden ruft die GUI-Hauptschleife die Funktion zum aktualisiseren der Werte und Schalten auf, und während die läuft kann in der selben Zeit die GUI nicht reagieren.

Die Lösung ist üblicherweise die länger laufenden Aufgaben nebenläufig in einem eigenen Thread laufen zu lassen. Schau Dir mal das `threading`-Modul an. Aber Achtung: Die GUI darf nur von dem Thread aus verändert werden in dem die GUI-Hauptschleife läuft! Man kann zwischen den beiden Threads zum Beispiel mit einer `Queue.Queue` kommunizieren, die von der Tk-Seite wie bisher alle x Sekunden abgefragt wird.

Die ersten beiden Funktionen sind fast identisch, die kann man sehr einfach zu einer zusammenfassen, welche den Unterschied als Argument bekommt. Oder man lässt das gleich ganz und ruft die nur einmal auf, denn so wie das Programm jetzt läuft wird die Temperatur alle 5 Sekunden *vier* mal ausgelesen, obwohl das nur einmal wirklich nötig wäre.
Antworten