GPh*_*ilo 3 python qt qthread qml pyside2
我有一个 python 定义的工作器QObject,它有一个work()由 QML UI 调用的慢速插槽(在我的实际 UI 中,FolderListModel当用户浏览列表时,该方法在每个项目上动态调用,但对于他的示例代码我'我只是在窗口完成时调用它作为示例)。
我想work异步运行慢速以防止 UI 阻塞。我想通过在 QThread 上移动 Worker 实例并在那里调用插槽来做到这一点,但这不起作用,因为 UI 仍然被阻塞,等待结果的work()到来。
这是我迄今为止尝试的代码:
mcve.qml:
import QtQuick 2.13
import QtQuick.Window 2.13
Window {
id: window
visible: true
width: 800
height: 600
title: qsTr("Main Window")
Component.onCompleted: console.log(worker.work("I'm done!")) // not the actual usage, see note in the question
}
Run Code Online (Sandbox Code Playgroud)
mcve.py:
import QtQuick 2.13
import QtQuick.Window 2.13
Window {
id: window
visible: true
width: 800
height: 600
title: qsTr("Main Window")
Component.onCompleted: console.log(worker.work("I'm done!")) // not the actual usage, see note in the question
}
Run Code Online (Sandbox Code Playgroud)
如何work()异步调用,以便仅在完成后应用其效果?而且,作为奖励,我在使用 QThreads 时在做什么/理解错误?
# ...
import threading
class Worker(QObject):
@Slot(str, result=str)
def work(self, path):
print(threading.current_thread())
sleep(5) # do something lengthy
return path
# ...
Run Code Online (Sandbox Code Playgroud)
输出:
<_MainThread(MainThread, started 140409078408832)>
qml: I'm done!
Run Code Online (Sandbox Code Playgroud)
如您所见,“work”方法在主线程中执行,导致它阻塞 GUI。
为什么在主线程中执行“work”方法?方法或函数在调用它的上下文中执行,在您的情况下,在主线程中执行的 QML 中。
那么如何在 QObject 所在的线程中执行一个方法呢?好吧,您必须异步使用QMetaObject::invokeMethod()(此方法在 PySide2 中无法用于错误),通过信号调用或使用QTimer::singleShot().
在这些情况下,最好创建一个桥(QObject)来调用在另一个线程中执行的函数/方法,并通过信号通知更改。
<_MainThread(MainThread, started 140409078408832)>
qml: I'm done!
Run Code Online (Sandbox Code Playgroud)
import QtQuick 2.13
import QtQuick.Window 2.13
Window {
id: window
visible: true
width: 800
height: 600
title: qsTr("Main Window")
Component.onCompleted: bridge.startSignal("I'm done!")
Connections{
target: bridge
onResultChaged: console.log(result)
}
}
Run Code Online (Sandbox Code Playgroud)