暂停python脚本,直到事件发生而没有挂起/阻止GUI [英] Pause a python script until an event occurs without hanging/blocking the GUI

查看:99
本文介绍了暂停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.

  • 同时/睡眠:等待文本输入变量包含有效结果.但这阻止了Kivy中正在进行的textinput GUI

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

缺少原始输入: 目前正在考虑尝试使用此技巧,这将允许我停止脚本,然后反馈由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,则可以使用Deferred s和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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆