Python脚本如何在不阻塞GUI的情况下等待事件发生?

4

我正在尝试使用Kivy迁移从PyQt编写的代码,但是我无法想象出解决方案。

我有数千行代码使用Qt的对话框进行文本输入。也就是说,当达到他们的代码行时,他们会"停止"脚本直到按下"确定"按钮,以便返回文本输入。

Kivy没有这个功能,因此理想情况下,当程序需要用户输入时,"确定"按钮将调用下一个要运行的函数。

因此,我必须用一个函数来替换所有当前对PyQt函数的调用,该函数可以停止正在运行的脚本,启动工作响应的对话框,然后在它请求的文本输入可用时恢复原始脚本。所以问题是:

有没有一种方法可以停止正在运行的脚本,直到函数完成,而不会挂起GUI?

我已经尝试过:

  • 线程

即使我在新的线程中启动文本输入:

t = threading.Thread(target=TextInput.waiter)

调用此线程的函数将在调用文本输入后立即返回。 如果我使用以下代码:

t.start()
t.join()

主要脚本将停止,但同时也挂起了文本输入GUI。
- While/Sleep:等待文本输入变量包含有效结果,但这会阻塞在Kivy中进行的文本输入GUI。 - 通过黑客手段修改raw_input:目前考虑尝试某些黑客手段,这样可以停止脚本,然后反馈由Kivy文本输入弹出窗口找到的输入。
如果有任何建议,欢迎提出,感谢您的阅读。
1个回答

4
您不能仅仅暂停正在运行的脚本。相反,您需要重构您的程序以成为事件驱动(因为Kivy是一个事件驱动的GUI)。
下面是一个简单的示例函数:
def myfunc():
    # do some stuff here
    # now we need some input...
    val = qt_input_dialogue()
    # do some more stuff here

重构:

class MyPopup(Popup):
    value = StringProperty() # bind this to a TextInput or something

def myfunc1():
    # do some stuff here
    p = MyPopupClass()
    p.bind(on_dismiss=lambda *_: myfunc2(p.value))
    p.open()

def myfunc2(val):
    # do some more stuff here

如果您愿意使用Twisted,在使用DeferredinlineCallbacks的情况下,您可以使这个过程更加轻松。
from kivy.support import install_twisted_reactor
install_twisted_reactor()

from twisted.internet import defer

Builder.load_string('''
<MyPopup>:
    BoxLayout:
        orientation: 'vertical'
        TextInput:
            id: text_input
        BoxLayout:
            orientation: 'horizontal'
            Button:
                text: 'OK'
                on_press: root.okfn(text_input.text)
''')

class MyPopup(Popup):
    def show(self, *args):
        d = defer.Deferred()
        self.okfn = d.callback
        self.open(*args)
        return d

@defer.inlineCallbacks
def myfunc():
    # do some stuff here
    val = yield MyPopup().show()
    # do some more stuff here

这样,你可以用yield MyPopup().show()替换QT输入对话框的调用。

非常感谢您的时间。问题在于成千上万行的代码将很难改为事件驱动,尽管如果这是唯一的选择,我应该开始着手处理,Kivy值得付出努力! - I want badges
@Iwantbadges 好的,如果你感兴趣,我添加了一个使用Twisted的示例。它具有能够像旧代码一样工作的优点 - 函数的执行通过yield语句暂停。 - kitti
这太棒了,我真的很感激。测试过了,它可以完全替代我之前使用的Qt。再见Qt! - I want badges

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接