我想模拟一个反复按下的按钮。示例:如果按下按钮2,则按钮1应该激活,并在设定的时间间隔内点亮for循环中设置的次数。我简化了下面的代码。
问题是,trigger_action()方法中的'duration'属性不能正确地调节循环的时间,并且打印功能和按钮立即亮起。
我试图在for循环中插入time.sleep()函数以“减慢速度”。这确实可以正确计时打印功能,但是,模拟的按钮按下(按钮点亮)不是按固定的间隔发生,而是一次完成。
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
class TestApp(App):
def build(self):
layout = BoxLayout()
self.b1 = Button(text="Button 1", on_press=self.on_press_button_1)
self.b2 = Button(text="Button 1", on_press=self.on_press_button_2)
layout.add_widget(self.b1)
layout.add_widget(self.b2)
return layout
def on_press_button_1(self, *args):
print("on press button 1")
def on_press_button_2(self, *args):
for x in range(5):
self.b1.trigger_action(0.5)
print(x, "on press button 2")
if __name__ == "__main__":
TestApp().run()
答案 0 :(得分:0)
使用kivy进行编程时,必须记住所有GUI事件都在主线程上发生,并且所有代码(除非采取预防措施)也将在主线程上运行。因此,您的for
循环正在主线程上运行,并且如果您向该循环中添加sleep
,它也将在主线程上运行。因此该代码使主线程处于繁忙状态。结果是您的所有trigger_action
调用(以及任何其他更改GUI的调用)都必须等到您的代码停止保留主线程之后才能影响GUI。因此,在您的for
循环结束时,GUI有机会赶上来,并且所有等待的GUI按钮效果都已执行,并显示为一长按。通常,您希望GUI事件调用的任何方法(例如按下按钮)尽快返回或创建新线程进行冗长的处理。
因此,这是使代码正常工作的一种方法:
from kivy.app import App
from kivy.clock import Clock
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
class TestApp(App):
def build(self):
layout = BoxLayout()
self.b1 = Button(text="Button 1", on_press=self.on_press_button_1)
self.b1.click_count = 0
self.max_clicks = None
self.clock_event = None
self.b2 = Button(text="Button 2", on_press=self.on_press_button_2)
layout.add_widget(self.b1)
layout.add_widget(self.b2)
return layout
def on_press_button_1(self, *args):
print("on press button 1")
if self.max_clicks is not None and self.clock_event is not None:
self.b1.click_count += 1
if self.b1.click_count >= self.max_clicks:
self.clock_event.cancel()
self.clock_event = None
self.max_clicks = None
def on_press_button_2(self, *args):
self.max_clicks = 5
self.b1.click_count = 0
self.clock_event = Clock.schedule_interval(lambda dt: self.b1.trigger_action(), 1)
if __name__ == "__main__":
TestApp().run()
这使用Clock.schedule_interval
来安排某些内容在主线程上运行,但立即返回,以允许GUI正常运行。 Clock.schedule_interval()
使用参数dt
(自计划事件以来的时间)调用指定的方法,但是trigger_action()
不需要这样的参数,因此我使用了{{1 }}。参见documentation。 lambda
,click_count
和max_clicks
仅用于管理事件的取消。