更新2:如何在while循环中停止函数?

时间:2016-06-10 16:23:48

标签: python-3.x tkinter raspberry-pi

更新

因此,我成功实现了线程,以允许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()

3 个答案:

答案 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
    >