Kivy - Как я могу вызвать trigger_action () в цикле и правильно ли он работает? - PullRequest
0 голосов
/ 05 февраля 2019

Я хотел бы смоделировать нажатие кнопки несколько раз.Пример: если я нажму кнопку 2, кнопка 1 должна активироваться и высветить количество раз, установленное в цикле for за заданный интервал времени.Я упростил код ниже.

Проблема в том, что атрибут 'duration' в методе trigger_action () неправильно регулирует время цикла, а функция печати и подсветка кнопок происходят мгновенно.

Я пыталсявставить функцию time.sleep () в цикл for для «замедления».Это работает для правильного определения времени функции печати, однако симулированные нажатия кнопок (загорание кнопок) происходят не через регулярный интервал, а скорее все сразу.

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()

1 Ответ

0 голосов
/ 08 февраля 2019

При программировании с использованием kivy, вы должны иметь в виду, что все события GUI происходят в главном потоке, и весь ваш код (если вы не принимаете меры предосторожности) также будет выполняться в главном потоке.Таким образом, ваш цикл for выполняется в главном потоке, и если вы добавите sleep в этот цикл, он также будет выполняться в основном потоке.Так что этот код делает основной поток занятым.В результате все ваши trigger_action вызовы (и любые другие вызовы, которые изменяют GUI) должны ждать, пока ваш код перестанет удерживать основной поток, прежде чем они смогут повлиять на GUI.Таким образом, в конце цикла for графический интерфейс получает шанс наверстать упущенное, и все ожидаемые эффекты кнопок графического интерфейса предварительно формируются и отображаются как одно длинное нажатие кнопки.В общем, вы хотите, чтобы любой метод, вызываемый событием графического интерфейса пользователя (например, нажатие кнопки), возвращался как можно быстрее или создавал новый поток для длительной обработки.

Итак, вот способ сделатьваш код работает:

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, который планирует что-то для запуска в главном потоке, но немедленно возвращается, что позволяет графическому интерфейсу работать нормально.Clock.schedule_interval() вызывает указанный метод с аргументом dt (время с момента планирования события), но trigger_action() не хочет такого аргумента, поэтому я использовал lambda.См. документация .click_count, max_clicks и clock_event используются только для управления отменой события.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...