主循环中的Python While循环导致延迟 [英] Python While loop within mainloop causing lag

查看:388
本文介绍了主循环中的Python While循环导致延迟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我使用root.mainloop()中包含的while True:循环运行代码时,这使我的GUI严重滞后,并且代码无法按我希望的那样平稳运行.我想知道如何使我的代码流畅运行且没有滞后.

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.

预先感谢您的帮助.

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

推荐答案

只需使用TK对象的after方法.这不会影响重绘,也不需要调用任何手动更新函数,因为它会延迟该代码的执行,直到gui线程不忙为止.

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.

将要独立执行的代码拆分为一个单独的函数,并将其与时间延迟一起传递给root.after.我第一次使用0的延迟,因此它立即执行.然后在函数末尾再次调用它,这一次将值1000(毫秒)作为延迟传递.它将重复执行,直到您结束tkinter应用为止.

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

这篇关于主循环中的Python While循环导致延迟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆