2017-04-04 2 views
0

Lorsque j'exécute le code avec la boucle while True: incluse dans le root.mainloop(), cela ralentit fortement mon interface graphique et le code ne fonctionne pas aussi bien que je le voudrais. Je me demande comment je rends mon code fluide et sans décalage. Pour les besoins de ce test, j'ai commenté de grandes sections du code qui ne fonctionnent que lorsqu'il est raccordé à mon pi de framboise.Python While loop within mainloop provoquant un décalage

Merci d'avance pour votre aide.

import os 
import glob 
import time 
#import RPi.GPIO as GPIO 
from datetime import datetime 
from tkinter import * 

''' 
#Set gpio's 
GPIO.setmode(GPIO.BCM) 
GPIO.setwarnings(False) 
GPIO.setup(17,GPIO.OUT)#RED 
GPIO.setup(22,GPIO.OUT)#GREEN 
GPIO.setup(27,GPIO.OUT)#BLUE 


#grab temp probe information 
os.system('modprobe w1-gpio') 
os.system('modprobe w1-therm') 

base_dir = '/sys/bus/w1/devices/' 
device_folder = glob.glob(base_dir + '28*')[0] 
device_file = device_folder + '/w1_slave' 


# Read temperature from device 

def read_temp_raw(): 
    f = open(device_file, 'r') 
    lines = f.readlines() 
    f.close() 
    return lines 

def read_temp(): 
    lines=read_temp_raw() 
    while lines[0].strip()[-3:] != 'YES': 
     time.sleep(0.1) 
     lines = read_temp_raw() 
    equals_pos = lines[1].find('t=') 
    if equals_pos != -1: 
     temp_string = lines[1][equals_pos+2:] 
     temp_c = float(temp_string)/1000 
     #temp_f = temp_c * 9.0/5.0 + 32.0 
     return temp_c#, temp_f 

''' 
temp = 18 
desiredtemp = 17 
deg = u'\xb0'#utf code for degree 

#increase button press 
def increase(): 
    global desiredtemp 
    desiredtemp += 0.5 
    tmpstr.set("%s" % desiredtemp) 


#Decrease button press 
def decrease(): 
    global desiredtemp 
    desiredtemp -= 0.5 
    tmpstr.set("%s" % desiredtemp) 




#Tkinter start 
root = Tk() 
root.wm_title("Temp") #Name the title bar 

#code to add widgets will go here.... 

#make 3 frames for text and buttons 
topFrame = Frame(root) 
topFrame.pack(side=TOP) 

middleFrame = Frame(root) 
middleFrame.pack() 

bottomFrame = Frame(root) 
bottomFrame.pack(side=BOTTOM) 

tmpstr = StringVar(value="%s" % desiredtemp) 
crtmpstr = StringVar(value="%s" % temp) 

#Set labels 
label1 = Label(topFrame, text="Desired Temp = ", fg="black") 
label2 = Label(middleFrame, text="Actual Temp = ", fg="black") 
label3 = Label(topFrame, textvariable=tmpstr, fg="black") 
label4 = Label(middleFrame, textvariable=crtmpstr, fg="black") 

#use to put labels on screen 
label1.pack(side=LEFT) 
label2.pack(side=LEFT) 
label3.pack(side=LEFT) 
label4.pack(side=LEFT) 

#Set buttons 
button1 = Button(bottomFrame, text="Increase (0.5"+ deg +"C)", fg="black", command=increase) 
button2 = Button(bottomFrame, text="Decrease (0.5"+ deg +"C)", fg="black", command=decrease) 

#use to put buttons on screen 
button1.pack(side=LEFT) 
button2.pack(side=LEFT) 


#Tkinter End 


# Open file to be logged 
''' 
file = open("/home/pi/Desktop/Templog.csv", "a") 

if os.stat("/home/pi/Desktop/Templog.csv").st_size == 0: 
    file.write("Date, Time, TemperatureSensor1\n") 

''' 


# Continuous print loop 
while 1: 
    print(temp) 
    if(temp<=desiredtemp): 
     #GPIO.output(17,GPIO.LOW) 
     #GPIO.output(22,GPIO.HIGH) 
     temp += 5 
     crtmpstr.set("%s" % temp) 
    else: 
     #GPIO.output(17,GPIO.HIGH) 
     #GPIO.output(22,GPIO.LOW) 
     temp -=0.5 
     crtmpstr.set("%s" % temp) 

    #now = datetime.now() 
    #file.write(str(now.day)+"-"+str(now.month)+"-"+str(now.year)+","+str(now.hour)+":"+str(now.minute)+":"+str(now.second)+","+str(read_temp())+"\n") 
    #file.flush() 
    time.sleep(1) 
    root.update() 



root.mainloop() 
+0

Avez-vous étudié la question que je lié précédemment http://stackoverflow.com/questions/459083/how-do-you-run-your-own-code-alongside-tkinters-event-loop –

Répondre

1

utiliser simplement la méthode after d'objet TK. Cela n'affectera pas le redessin et ne nécessitera pas l'appel de fonctions de mise à jour manuelle, car il reporte l'exécution de ce code jusqu'à ce que le thread gui ne soit pas occupé.

Fractionner le code à exécuter indépendamment en une fonction distincte et le passer à root.after avec une temporisation. La première fois que j'ai utilisé un retard de 0, il s'exécute immédiatement. Puis à la fin de la fonction, appelez-le à nouveau, cette fois-ci en passant la valeur 1000 (millisecondes) comme un délai. Il sera exécuté à plusieurs reprises jusqu'à ce que vous terminiez l'application tkinter.

# ... other code here 

def gpiotask(): 

    global temp 

    print(temp) 
    if(temp <= desiredtemp): 
     GPIO.output(17, GPIO.LOW) 
     GPIO.output(22, GPIO.HIGH) 
     temp += 5 # <- did you mean 0.5 here ? 
     crtmpstr.set("%s" % temp) 
    else: 
     GPIO.output(17, GPIO.HIGH) 
     GPIO.output(22, GPIO.LOW) 
     temp -= 0.5 
     crtmpstr.set("%s" % temp) 

    root.after(1000, gpiotask) 

root.after(0, gpiotask) 
root.mainloop() 
+0

Cette instruction est fausse: _ "la méthode after ... vous permet d'exécuter une fonction loin du thread graphique" _. Ce n'est pas ce que "après" fait. 'after' exécute toujours le code dans le même thread. Tout ce que 'after' fait, c'est que les horaires doivent être travaillés plus tard. –

+0

Ok merci @BrianOakley. J'ai pris une estimation de ce qu'il a fait. Je vais retirer cela de ma réponse. Je suppose que le nom a un sens alors. –