問題描述
嘗試使用 Kivy 從 PyQt 遷移,我什至無法想象解決方案.
Trying to migrate from PyQt with Kivy and I cant even imagine a solution for this.
我有數(shù)千行代碼使用 Qt 的對話進行文本輸入.也就是說,當?shù)竭_他們的代碼行時,他們會停止"腳本,直到按下確定"按鈕,這樣他們就可以返回文本輸入.
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 函數(shù)的調用替換為一個函數(shù),該函數(shù)會停止正在運行的腳本,啟動一個有效的響應式對話,然后在它有請求的文本輸入時恢復原始對話.所以問題是:
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:
有沒有辦法在函數(shù)完成之前停止正在運行的腳本,不掛起 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)
調用此類線程的函數(shù)將在調用文本輸入后立即返回.如果我使用此代碼:
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).
這是一個簡單的示例函數(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
重構:
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 輸入對話的調用替換為 yield MyPopup().show()
.
This way, you can just replace the calls to QT input dialogues with yield MyPopup().show()
.
這篇關于暫停 python 腳本,直到事件發(fā)生而不掛起/阻塞 GUI的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!