問(wèn)題描述
嘗試使用 Kivy 從 PyQt 遷移,我什至無(wú)法想象解決方案.
Trying to migrate from PyQt with Kivy and I cant even imagine a solution for this.
我有數(shù)千行代碼使用 Qt 的對(duì)話進(jìn)行文本輸入.也就是說(shuō),當(dāng)?shù)竭_(dá)他們的代碼行時(shí),他們會(huì)停止"腳本,直到按下確定"按鈕,這樣他們就可以返回文本輸入.
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 沒(méi)有該功能,因此理想情況下,當(dāng)程序需要用戶輸入時(shí),確定"按鈕會(huì)調(diào)用下一個(gè)功能來(lái)運(yùn)行.
Kivy doesnt have that functionality, so ideally, when the program needs user input, the "ok" button would call for the next function to run.
因此,我必須將所有當(dāng)前對(duì) PyQt 函數(shù)的調(diào)用替換為一個(gè)函數(shù),該函數(shù)會(huì)停止正在運(yùn)行的腳本,啟動(dòng)一個(gè)有效的響應(yīng)式對(duì)話,然后在它有請(qǐng)求的文本輸入時(shí)恢復(fù)原始對(duì)話.所以問(wèn)題是:
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:
有沒(méi)有辦法在函數(shù)完成之前停止正在運(yùn)行的腳本,不掛起 GUI?
Is there a way to stop a running script until a function finishes, without hanging the GUI?
我已經(jīng)試過(guò)了:
- 線程:
即使我在新線程中開(kāi)始文本輸入:
Even if I start the text input in a new thread:
t = threading.Thread(target=TextInput.waiter)
調(diào)用此類線程的函數(shù)將在調(diào)用文本輸入后立即返回.如果我使用此代碼:
the function that calls such thread will return just after calling the text input. If I use this code:
t.start()
t.join()
主腳本將停止,但也會(huì)掛起文本輸入 GUI.
The main script will stop, but also hangs the text input GUI.
While/Sleep:等待文本輸入變量包含有效結(jié)果.但這會(huì)阻止 Kivy 中正在進(jìn)行的文本輸入 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.
非常歡迎任何指點(diǎn),感謝閱讀.
Any pointers would be really welcome, thanks for reading.
推薦答案
你不能只是暫停正在運(yùn)行的腳本.相反,您需要將程序重構(gòu)為事件驅(qū)動(dòng)(因?yàn)?Kivy 是事件驅(qū)動(dòng)的 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).
這是一個(gè)簡(jiǎn)單的示例函數(shù):
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
重構(gòu):
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 Deferred
s 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 輸入對(duì)話的調(diào)用替換為 yield MyPopup().show()
.
This way, you can just replace the calls to QT input dialogues with yield MyPopup().show()
.
這篇關(guān)于暫停 python 腳本,直到事件發(fā)生而不掛起/阻塞 GUI的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!