更新
因此,我成功实现了线程,以允许GUI在进程运行时保持解除阻塞状态。现在我想弄清楚如何让这个循环中断并仍能正常运行。
我尝试实现第二个变量,while语句作为一个标志,在一次运行PUMP函数之后尝试打破while循环。但是,现在PUMP功能根本不运行。 GPIO引脚永远不会变高。 我正在寻找这个:
- 按下按钮。 -Sets Flag to 1 - 如果浮动开关为高,则在线程中运行RUN()函数;如果浮动开关为低,则表示低水位信号 - 运行PUMP()函数时,RUN()检查标志和浮动开关的状态 - PUMP()将GPIO引脚置为高电平,5秒后调用OFF()函数 - OFF()将标志设置为0并将泵GPIO设置为低电平
如果在PUMP()期间浮动开关变为低电平,它应触发并调用LOW()功能,通过将GPIO引脚设置为低电平并显示状态来停止泵。这也将标志设置为0。
代码:
from tkinter import *
import tkinter.font
import RPi.GPIO as GPIO
import threading
#Variables
Flag = 0
#GPIO Setup
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(16, GPIO.OUT) #Water Pump
GPIO.setup(18, GPIO.IN) #Tank Float Switch
GPIO.output(16, GPIO.LOW)
#Window Setup
win = Tk()
win.title("Pump Test")
win.geometry("150x150+0+0")
#Label Setup
Label (win, text="Water System", fg="red", bg="black", font="24").grid(row=0, column=0)
#Functions
def RUN ():
while GPIO.input(18) and Flag == 1:
PUMP()
if Flag == 0:
OFF()
elif GPIO.input(18) == False:
LOW()
def OFF ():
Flag = 0
GPIO.output(16, GPIO.LOW)
WTR.config(text="Water", bg="grey")
def LOW ():
Flag = 0
GPIO.output(16, GPIO.LOW)
WTR.config(text="LOW WATER", bg="red")
def WTR ():
Flag = 1
if GPIO.input(18):
threading.Thread(target=RUN).start()
if GPIO.input(18)== False:
threading.Thread(target=LOW).start()
def PUMP ():
GPIO.output(16, GPIO.HIGH)
win.after(5000, OFF)
#Buttons
WTR = Button(win, text="Water", bg="grey", command = WTR, height = 2, width = 8)
WTR.grid(row=1, column=0) #Water Pump Control
mainloop()
答案 0 :(得分:2)
为了确保UI保持对用户事件(鼠标点击等)以及系统事件(如曝光和重新绘制)的响应,您不应该在函数中输入长期循环,也不要使用sleep
。相反,Tkinter提供after
方法,允许您安排在一段时间后完成某些事情。此调用将您的调用添加到事件队列中,并由mainloop
调用的代码在适当的时候对其进行处理。对于在延迟之后应该发生的事情,显然使用了after(num_millis)
。如果您需要轮询引脚的状态,然后使用短时间并在处理程序中设置另一个after
调用以再次调用您的轮询功能。请注意,如果您保留调用方法时返回的after
值,则可以取消id
来电。
不要使用time.sleep
。睡眠期间不会处理任何UI事件,UI将会死亡。使用after
。
答案 1 :(得分:1)
您的Flag
是模块级变量。
如果你想在函数中修改(不将其作为参数传递),你需要在函数中将其标记为 global 。
观察:
In [1]: flag = 0
In [2]: def foo(num):
...: flag = num
...:
In [3]: flag
Out[3]: 0
In [4]: foo(4)
In [5]: flag
Out[5]: 0
In [6]: foo(12)
In [7]: flag
Out[7]: 0
调用foo
设置flag
,但这是函数的本地!它对模块级对象没有影响。
您必须明确说明要修改模块级变量:
In [8]: def bar(num):
...: global flag
...: flag = num
...:
In [9]: bar(4)
In [10]: flag
Out[10]: 4
In [11]: bar(7)
In [12]: flag
Out[12]: 7
答案 2 :(得分:0)
感谢@patthoyts和@RolandSmith提供的有助于我找到答案的见解。
他们说的两件事很有帮助 - 不使用time.sleep并确保我使用的是全局变量。
有一些关于Flag想法的重新工作,而不是睡觉,而是创建一个检查功能,看看已经过了多少时间。暂时删除了线程,因为它对GUI进程来说并不可怕。汤姆·斯利克(Tom Slick)对幕后的帮助大声呼喊!
> inspect common/update:resolvers
[info] Setting: scala.collection.Seq[sbt.Resolver] = List()
[info] Description:
[info] The user-defined additional resolvers for automatically managed dependencies.
[info] Provided by:
[info] */*:resolvers
[info] Defined at:
[info] (sbt.Classpaths) Defaults.scala:1122
[info] Delegates:
[info] common/update:resolvers
[info] common/*:resolvers
[info] {.}/update:resolvers
[info] {.}/*:resolvers
[info] */update:resolvers
[info] */*:resolvers
[info] Related:
[info] root/*:resolvers
[info] */*:resolvers
>