Kivy-如何在循环中调用trigger_action()并使其正常工作



我想模拟一个反复按下的按钮。示例:如果我按下按钮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()

使用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()不需要这样的参数,所以我使用了lambda。请参阅文档。click_countmax_clicksclock_event仅用于管理取消事件。

最新更新