【问题标题】:How to break a while loop in Kivy?如何打破 Kivy 中的 while 循环?
【发布时间】:2016-05-09 04:22:02
【问题描述】:

这里我有一个 runStuff 函数,我想重复运行 saySomething() 函数,但按下退出按钮后会退出。

当前正在运行 while 循环,不允许输入退出按钮。

def saySomething():
    ttsSpeak('Say this phrase')

def runStuff(self):
    while True:
        if App.get_running_app().stop() != True:
            saySomething()
            time.sleep(2)
        else: break

def exit(self):
    App.get_running_app().stop()

class AudibleCoachApp(App):
    def build(self):
        layout = BoxLayout(padding=7, spacing=3, orientation='vertical') # set layout of the screen
        btn1 = Button(text='Start it', size_hint=(1, .66)) # create a button instance
        btn1.bind(on_press=runStuff) # binding the button with the function below
        btn3 = Button(text='Exit', size_hint=(1, .17)) # create a button instance
        btn3.bind(on_press=exit) # binding the button with the function below
        layout.add_widget(btn1) # physically add the button onto the layout
        layout.add_widget(btn2) # physically add the button onto the layout
        layout.add_widget(btn3) # physically add the button onto the layout 

        return layout

if __name__ == '__main__':
    AudibleCoachApp().run()

【问题讨论】:

  • 在您的 while 循环条件中调用 stop() 的真正意思是什么?您似乎正在寻找可以告诉您应用程序是否停止的信息?
  • 不太确定您的问题。只要未按下退出按钮,我希望 runStuff() 继续调用 saySomething() 。当按下退出按钮时,我希望它执行退出功能。
  • 好吧,你在两个不同的地方打电话给stop(),你似乎希望它在每个地方都能做一些完全不同的事情。在某个地方,您希望它停止您的程序。另一方面,您希望它检查您是否已停止该程序。但是你以完全相同的方式调用它,Python 无法读懂你的想法。所以其中一个电话肯定是错的……我就是这么说的。
  • 我是 kivy 新手,对如何在 runStuff() 循环中激活 stop() 有点困惑。
  • 您可能会看到问题,因为您在回调函数中放置了带有time.sleep() 的循环。如果你想每 X 秒运行一次,看起来你应该使用Clock

标签: android python-2.7 while-loop kivy


【解决方案1】:

无限循环在 UI 编程中很少是一个好的解决方案,因为它们会阻塞运行它们的整个线程。最好使用kivy的Clock对象来调度你的方法。

from kivy.clock import Clock

def runStuff(self):
    Clock.schedule(saySomething, 2)

然后可以使用Clock.unschedule 取消安排回调。

def exit(self):
    App.get_running_app().stop()
    Clock.unschedule(saySomething)

此外,通常不鼓励使用get_running_app,因为将所有可以访问应用程序的函数作为应用程序的方法是一种很好的做法。由于您在每个函数中都包含了 self 参数,我认为这就是您打算做的事情。

class AudibleCoachApp(App):

    def runStuff(self):
        Clock.schedule(saySomething, 2)

    def exit(self):
        Clock.unschedule(saySomething)
        self.stop()

您必须将build 中的runStuffexit 呼叫更改为self.runStuffself.exit

btn1.bind(on_press=self.runStuff) # binding the button with the function          

...

btn3.bind(on_press=self.exit) # binding the button with the function below

而且,您需要显式绑定应用程序以阻止 Clock 被 GC。

if __name__ == '__main__':
    app = AudibleCoachApp()
    app.run()

总之,代码变成如下(别忘了加上Clock from kivy.clock的导入)。

import pyttsx
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock

# ...

def saySomething():
    ttsSpeak('Say this phrase')

class AudibleCoachApp(App):

    def runStuff(self):
        Clock.schedule_interval(saySomething, 2)

    def exit(self):
        Clock.unschedule(saySomething)
        self.stop()

    def build(self):
        layout = BoxLayout(padding=7, spacing=3, orientation='vertical') # set layout of the screen
        btn1 = Button(text='Start it', size_hint=(1, .66)) # create a button instance
        btn1.bind(on_press=self.runStuff) # binding the button with the function below
        btn2 = Button()
        btn3 = Button(text='Exit', size_hint=(1, .17)) # create a button instance
        btn3.bind(on_press=self.exit) # binding the button with the function below
        layout.add_widget(btn1) # physically add the button onto the layout
        layout.add_widget(btn2) # physically add the button onto the layout
        layout.add_widget(btn3) # physically add the button onto the layout 

        return layout

if __name__ == '__main__':
    app = AudibleCoachApp()
    app.run()

请注意,以上所有代码均未经测试。如果您发现任何错误,请发表评论。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-13
    • 2020-09-18
    • 2020-03-28
    • 1970-01-01
    • 1970-01-01
    • 2021-07-02
    相关资源
    最近更新 更多