python-3.x - 在Qt(PySide2)的主线程上调用函数的简单方法
问题描述
是否有任何简单的方法可以从任何其他线程或 QThread 调用主线程中的函数或方法?
我听说Slot
s 和Signal
s 可以用作线程和主线程之间的代理,但是每次我想将数据传输到主线程时,创建这样的代理感觉工作量太大。
(我的回答描述了一种非常通用的方法来完成这个,所以我不会在这里提供一个“最小”的例子,你可以看看答案。)
解决方案
Qt 有一个名为invokeMethod
( https://doc.qt.io/qt-5/qmetaobject.html#invokeMethod ) 的函数,可用于通过使用Qt.QueuedConnection
连接类型调用主线程上的方法。
但是,在 PySide 中,如果您想调用带参数的函数,这将不起作用!
解决方案:
因此,为了让 PySide 具有类似甚至更简单的功能,我编写了这个类,每次你想在主线程上运行一个函数或方法时都可以使用它:
from typing import Callable
from PySide2.QtCore import QObject, Signal, Slot
from PySide2.QtGui import QGuiApplication
class InvokeMethod(QObject):
def __init__(self, method: Callable):
"""
Invokes a method on the main thread. Taking care of garbage collection "bugs".
"""
super().__init__()
main_thread = QGuiApplication.instance().thread()
self.moveToThread(main_thread)
self.setParent(QGuiApplication.instance())
self.method = method
self.called.connect(self.execute)
self.called.emit()
called = Signal()
@Slot()
def execute(self):
self.method()
# trigger garbage collector
self.setParent(None)
这将在内部创建没有任何参数的 aSignal
和 a 。Slot
但是将Slot
在主线程上调用,因为它已使用Qt.AutoConnection
(默认)连接并使用moveToThread(...)
. 为了确保没有函数参数由于垃圾收集器而丢失,类的父级临时设置为QGuiApplication
实例(如果您不依赖QGuiApplication
. AnyQObject
作为父级,则可能需要更改此设置)。
下面是一个关于如何使用这个类的例子:
InvokeMethod(lambda: print("hello"))
推荐阅读
- scala - 路径依赖和内部类
- javascript - Highcharts 工具提示:在逗号分隔的字符串中引入换行符
- excel - 在同一图表中以条形图和折线图绘制每月和每日数据
- json - 有没有更快的方法来解析 Java 中有效整数的字符串?
- reactjs - 在选择控件中选取项目不会在页面上保持选中状态。
- groovy - 使用groovy从soapui中具有命名空间的XML节点获取属性值
- python - 如何正确使用 tf.scatter_update 进行 N 维更新?
- python - PyGitHub:获取存储库的提交总数
- c - 检测重复的程序
- breakpoints - 如何在 lldb 中打印断点 ID