本文介绍了暂停 python 脚本,直到事件发生而不挂起/阻塞 GUI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试使用 Kivy 从 PyQt 迁移,我什至无法想象解决方案.

Trying to migrate from PyQt with Kivy and I cant even imagine a solution for this.

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

I have thousands of lines of code that use Qt's dialogues for text input. That is, when their line of code is reached, they 'stop' the script until the "ok" button is pressed, so they can return the text input.

Kivy 没有该功能,因此理想情况下,当程序需要用户输入时,确定"按钮会调用下一个功能来运行.

Kivy doesnt have that functionality, so ideally, when the program needs user input, the "ok" button would call for the next function to run.

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

Therefore I must replace all the current calls to a PyQt function with a function that stops the running script, launches a working responsive dialogue, then resumes the original when it has the text input it requested. So the question is:

有没有办法在函数完成之前停止正在运行的脚本,不挂起 GUI?

Is there a way to stop a running script until a function finishes, without hanging the GUI?

我已经试过了:

  • 线程:

即使我在新线程中开始文本输入:

Even if I start the text input in a new thread:

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

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

the function that calls such thread will return just after calling the text input.If I use this code:

t.start()
t.join()

主脚本将停止,但也会挂起文本输入 GUI.

The main script will stop, but also hangs the text input GUI.

  • While/Sleep:等待文本输入变量包含有效结果.但这会阻止 Kivy 中正在进行的文本输入 GUI

  • While/Sleep: Waiting for the text input variable to contain a valid result. But this blocks the ongoing textinput GUI in Kivy

破解 raw_input:目前正在考虑尝试一些破解,这将允许我停止脚本,然后反馈由 kivy 文本输入弹出窗口找到的输入.

Hacking raw_input: Currently thinking into try some hack with that, that would allow me to stop the script, then feed back the input found by the kivy text input popup.

非常欢迎任何指点,感谢阅读.

Any pointers would be really welcome, thanks for reading.

推荐答案

你不能只是暂停正在运行的脚本.相反,您需要将程序重构为事件驱动(因为 Kivy 是事件驱动的 GUI).

You can't just pause the running script. Instead, you'll need to refactor your program to be event-driven (as Kivy is an event-driven GUI).

这是一个简单的示例函数:

Here's a simple example function:

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,你可以使用 Deferreds 和 inlineCallbacks 使这更容易.


If you're willing to use Twisted, you can make this even easier using Deferreds and inlineCallbacks.

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

这样,您只需将 QT 输入对话的调用替换为 yield MyPopup().show().

This way, you can just replace the calls to QT input dialogues with yield MyPopup().show().

这篇关于暂停 python 脚本,直到事件发生而不挂起/阻塞 GUI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-11 13:51