- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
根据 Qt 文档和网络上的其他示例,我认为以下使用 QThread.started
信号的程序会在 非主线程。但事实并非如此,而是从 main 线程调用每个 work
槽:
import time
import sys
from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QApplication, QPushButton, QTextEdit, QVBoxLayout, QWidget
def trap_exc_during_debug(*args):
# when app exits, put breakpoint in next line when run in debugger, and analyse args
pass
sys.excepthook = trap_exc_during_debug
class Checker(QObject):
sig_step = pyqtSignal(int, str)
sig_done = pyqtSignal(int)
def __init__(self, id: int):
super().__init__()
self.__id = id
@pyqtSlot()
def work(self):
thread_name = QThread.currentThread().objectName()
thread_id = int(QThread.currentThreadId())
print('running work #{} from thread "{}" (#{})'.format(self.__id, thread_name, thread_id))
time.sleep(2)
self.sig_step.emit(self.__id, 'step 1')
time.sleep(2)
self.sig_step.emit(self.__id, 'step 2')
time.sleep(2)
self.sig_done.emit(self.__id)
class MyWidget(QWidget):
NUM_THREADS = 3
sig_start = pyqtSignal()
def __init__(self):
super().__init__()
self.setWindowTitle("Thread Example")
form_layout = QVBoxLayout()
self.setLayout(form_layout)
self.resize(200, 200)
self.push_button = QPushButton()
self.push_button.clicked.connect(self.start_threads)
self.push_button.setText("Start {} threads".format(self.NUM_THREADS))
form_layout.addWidget(self.push_button)
self.log = QTextEdit()
form_layout.addWidget(self.log)
# self.log.setMaximumSize(QSize(200, 80))
self.text_edit = QTextEdit()
form_layout.addWidget(self.text_edit)
# self.text_edit.setMaximumSize(QSize(200, 60))
QThread.currentThread().setObjectName('main')
self.__threads_done = None
self.__threads = None
def start_threads(self):
self.log.append('starting {} threads'.format(self.NUM_THREADS))
self.push_button.setDisabled(True)
self.__threads_done = 0
self.__threads = []
for idx in range(self.NUM_THREADS):
checker = Checker(idx)
thread = QThread()
thread.setObjectName('thread_' + str(idx))
self.__threads.append((thread, checker)) # need to store checker too otherwise will be gc'd
checker.moveToThread(thread)
checker.sig_step.connect(self.on_thread_step)
checker.sig_done.connect(self.on_thread_done)
# self.sig_start.connect(checker.work) # method 1 works: each work() is in non-main thread
thread.started.connect(checker.work) # method 2 doesn't work: each work() is in main thread
thread.start()
self.sig_start.emit() # this is only useful in method 1
@pyqtSlot(int, str)
def on_thread_step(self, thread_id, data):
self.log.append('thread #{}: {}'.format(thread_id, data))
self.text_edit.append('{}: {}'.format(thread_id, data))
@pyqtSlot(int)
def on_thread_done(self, thread_id):
self.log.append('thread #{} done'.format(thread_id))
self.text_edit.append('-- Thread {} DONE'.format(thread_id))
self.__threads_done += 1
if self.__threads_done == self.NUM_THREADS:
self.log.append('No more threads')
self.push_button.setEnabled(True)
if __name__ == "__main__":
app = QApplication([])
form = MyWidget()
form.show()
sys.exit(app.exec_())
如果我改为使用自定义信号,则效果很好。要看到这一点,请注释掉“方法 2”行并取消注释“方法 1”行并重复运行。
在不必创建自定义信号的情况下启动工作人员肯定会更好,有没有办法做到这一点(同时坚持对工作人员调用 moveToThread
的设计)?
注意:QThread.started
信号的文档帮助不大:
This signal is emitted from the associated thread when it starts executing
对我来说,这意味着 started
将在非主线程中发出,这样它所连接的 work
插槽将在非主线程中被调用线程,但显然不是这样。即使我的解释不正确并且信号实际上是在主线程中发出的,连接类型对于这两种方法都是默认的Qt.AutoConnection
,到一个插槽QObject
移动到另一个线程,因此 started
信号应该被异步传输(即通过每个检查器的 QThread 事件循环),同样显然不是案件。
最佳答案
我向 jetbrains 发布了支持请求,他们迅速回复:
It was made intentionally for a better debugging. You can uncheck setting Settings | Build, Execution, Deployment | Python Debugger > PyQt compatible and will have workers started as expected.
太棒了!
关于python - 如何在非主线程 QObject 中开始工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41601862/
以下是我遇到的编译错误: /usr/lib/qt-3.3/include/qobject.h: In copy constructor Product::Product(const Product&)
class CHIProjectData : public QObject { public: CHIProjectData(); CHIProjectData(QMap aProje
这个问题在这里已经有了答案: Could I have copy constructor for subclass of QObject? (3 个答案) 关闭 7 年前。 我收到错误: C:\Qt
将一个项目从 Qt4 迁移到 Qt5 我得到了这个错误,我已经研究过,显然你不能从 QObject 创建一个派生类的复制构造函数(这太不可思议了,因为这段代码不是我的,它应该在以前的版本中编译).复制
我试图返回一个派生自 QObject 的类,但出现以下错误 Error : 'QObject::QObject' : cannot access private member declared in
我正在编写一些派生自 QObject 的 Qt 类,它看起来像: class A : public QObject { Q_OBJECT public: A() : QObject() {}
考虑以下代码: #include class A : public QObject { Q_OBJECT public: A(QObject* parent = 0)
我似乎需要 QObject 类型的 p 实例,我已经扩展了 QObject 并在 fileprocessor.h 中定义了关键字 Q_OBJECT,我不确定我还能做什么。 -文件处理器.h #ifnd
我有一个继承 QObject 的类 BatchItem,还有几个继承自 BatchItem 的类: #ifndef BATCHITEM_H #define BATCHITEM_H #include
这是代码: void invokeQMLFunction2Arg(QObject * object, QString func, QVariant p1, QVariant p2) { QMe
我读过 documentation对于 QObject::connect(对于 Qt 5.4),但我对重载有疑问 QMetaObject::Connection QObject::connect(co
我最近一直在使用QTCreator,我爱上了ATM。不幸的是,我想将它与 Python 一起使用,但我遇到了问题。我遇到的最大问题是发现我的应用程序上下文的子级返回 None。 main.py imp
使用 #include 有什么区别吗?和 #include ? 这两个似乎都有效,所以必须有一些原因来说明为什么 #include是首选吗? 最佳答案 任何不带 .h 扩展名的标准 Qt 头文件都保证
我写的Python代码看起来像这样: class Regularblock(QGraphicsItem): def __init__(self): super(QGraphic
Qt 框架有一个 signal for all QObjects which is emmited before destruction那个QObject。此事件可用于在它指向的对象被销毁时自动清空一
我想创建 SerialPort 类,它可以自动接收消息,然后发出信号。 但是当我编译它时显示错误信息: error: 'QObject' is an ambiguous base of 'Serial
(C++/Qt) 我有一个指向 QObject 的智能指针。让我们说一个 QWeakPointer。由于某些外部原因(可能发生在另一个对象中或由于某个事件),指向的对象可能会被销毁。因为我有一个智能指
QObject 析构函数的 Qt 引用说: 进出该对象的所有信号都会自动断开,该对象的任何未决发布事件都会从事件队列中删除。但是,使用 deleteLater() 通常比删除更安全直接一个 QObje
您好,我需要从后台进行一些套接字通信,我为此使用了QtConcurrent::run,但给了我警告。 QObject: Cannot create children for a parent that
如何打破 QObject 的父子所有权?似乎不再有明确的方法来做到这一点。打电话就够了 QObject::setParent(NULL) 最佳答案 你是对的。制作 QObject一个孤儿,简单地做 /
我是一名优秀的程序员,十分优秀!