所以,我有一个由Raspy控制的LED,还有一个只有一个按钮的基本GUI,我希望它的行为如下:
当我执行操作时,指示灯开始闪烁,但是该按钮没有显示。 当我中断程序时,按钮出现。为什么?
from tkinter import *
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setup(8, GPIO.OUT)
GPIO.output(8, False)
buttonPressed = False
master = Tk()
def callback():
GPIO.output(8, True)
buttonPressed = True
w = Button(master, text="Turn on light", command = callback)
w.pack()
while True:
if buttonPressed == False:
GPIO.output(8, True)
time.sleep(0.5)
GPIO.output(8, False)
time.sleep(0.5)
else:
GPIO.output(8, True)
答案 0 :(得分:3)
我认为@furas为您设定了正确的方向,但是由于我一直在努力工作,因此我想我也将解决方案留在这里。我拔出了GPIO代码,以便可以在本地运行它。
这两种解决方案的主要功能是,我们删除了对time.sleep
的调用,因为在进行time.sleep
处理时,Tk的事件循环无法处理任何事件(表现为在这些睡眠语句期间UI似乎“冻结”。
import time
import tkinter
buttonpressed = False
lastchange = 0
ledstate = False
def button_down(event):
global buttonpressed
print('BUTTON DOWN')
buttonpressed = True
def button_up(event):
global buttonpressed
print('BUTTON UP')
buttonpressed = False
def myloop(master):
global buttonpressed
global lastchange
global ledstate
now = time.time()
delta = now - lastchange
if not buttonpressed:
if now - lastchange > 0.5:
ledstate = not ledstate
print('LED', ledstate)
lastchange = now
else:
if not ledstate:
ledstate = True
print('LED', ledstate)
master.after_idle(myloop, master)
master = tkinter.Tk()
w = tkinter.Button(master, text="Turn on light")
w.bind('<ButtonPress>', button_down)
w.bind('<ButtonRelease>', button_up)
w.pack()
master.after(100, myloop, master)
master.mainloop()
答案 1 :(得分:3)
tkinter
应用程序需要调用.mainloop()
。
还应该使用.after(...)
函数来模拟while循环:
import tkinter as tk
import RPi.GPIO as GPIO
def led_on(state):
global button_pressed
button_pressed = state
def blink_led(state=True):
# turn on LED if either state or button_pressed is True
GPIO.output(8, state or button_pressed)
master.after(500, blink_led, not state) # toggle the state half a second later
# setup the RPi board
GPIO.setmode(GPIO.BOARD)
GPIO.setup(8, GPIO.OUT)
GPIO.output(8, False)
button_pressed = False
master = tk.Tk()
w = tk.Button(master, text='Turn on light')
w.pack()
w.bind('<ButtonPress-1>', lambda e: led_on(True)) # set button_pressed to True
w.bind('<ButtonRelease-1>', lambda e: led_on(False)) # set button_pressed to False
blink_led() # start the LED blinking
master.mainloop()
答案 2 :(得分:2)
我无法在RPi上对其进行测试,但我可能是这样的人。
普通command=
仅在您单击按钮时才能识别,但在释放按钮时却无法识别-您需要绑定事件<ButtonPress>
和<ButtonRelease>
,它们将在{{ 1}}和"mouse left button press"
我使用"mouse left button release"
来延迟运行功能,所以我不需要after()
和sleep()
可以阻塞while
(并且可以冻结所有GUI)。
而且我也不需要mainloop()
循环,因为我在while
和on_press
内全部运行,后来on_release
运行after()
并使用{{1 }}运行turn_off_led
,而after()
使用turn_on_led
再次运行after()
,因此它就像循环一样。
turn_off_led