Python While loop within mainloop causing lag

半城伤御伤魂 提交于 2020-01-17 06:10:48

问题


When I run the code with the while True: loop included within the root.mainloop() it is making my GUI lag heavily and the code does not run as smoothly as I would like. I am wondering how I make my code run smooth and without lag.

for the purpose of this test I have commented out large sections of the code that only work when it is hooked up to my raspberry pi.

Thank you in advance for your help.

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()

回答1:


Simply use the after method of TK object. This will not impact redrawing and will not require calling any manual update functions, as it defers the execution of that code until the gui thread is not busy.

Split the code to be executed independently into a separate function and pass it to root.after along with a time delay. The first time I used a delay of 0 so it executes immediately. Then at the end of the function call it again, this time passing the value 1000 (milliseconds) as a delay. It will execute repeatedly until you end the tkinter app.

# ... 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()


来源:https://stackoverflow.com/questions/43200770/python-while-loop-within-mainloop-causing-lag

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!