简体   繁体   English

Python PyQt5 线程 QObject:无法为不同线程中的父级创建子级

[英]Python PyQt5 threading QObject: Cannot create children for a parent that is in a different thread

I'm using Python 3.7.6 with PyQt5 on my Windows 10 computer.我在 Windows 10 计算机上使用 Python 3.7.6 和 PyQt5。 I am trying to write a simple application that will run three different procedures at the same time showing the output in three separate text boxes in the same window.我正在尝试编写一个简单的应用程序,它将同时运行三个不同的过程,在同一窗口的三个单独的文本框中显示输出。 I have tried to create some simple base code to add to, but am having an issue using the threading module with PyQt5.我试图创建一些简单的基本代码来添加,但是在使用 PyQt5 的线程模块时遇到了问题。 Here is my code:这是我的代码:

import sys, time
from threading import Thread

from PyQt5.QtWidgets import (
    QApplication, QMainWindow, QWidget, QPlainTextEdit, QHBoxLayout
    )

def run1():
    for i in range(20):
        text_1.setPlainText(text_1.toPlainText()  + (f"{i}\n"))
        time.sleep(0.0125)

def run2():
    for i in range(20):
        text_2.setPlainText(text_2.toPlainText()  + (f"{i}\n"))
        time.sleep(0.0125)

def run3():
    for i in range(20):
        text_3.setPlainText(text_3.toPlainText()  + (f"{i}\n"))
        time.sleep(0.0125)

app = QApplication([sys.argv])
win = QMainWindow()

text_1 = QPlainTextEdit()
text_2 = QPlainTextEdit()
text_3 = QPlainTextEdit()

my_widget = QWidget()
my_widget.layout = QHBoxLayout()
my_widget.layout.addWidget(text_1)
my_widget.layout.addWidget(text_2)
my_widget.layout.addWidget(text_3)
my_widget.setLayout(my_widget.layout)

win.setCentralWidget(my_widget)

t1 = Thread(target=run1)
t2 = Thread(target=run2)
t3 = Thread(target=run3)

t1.start()
t2.start()
t3.start()

t1.join()
t2.join()
t3.join()

win.show()

sys.exit(app.exec_())

When I run this code, it shows the desired output, but with multiple instances of the following error:当我运行此代码时,它显示了所需的输出,但出现以下错误的多个实例:

QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTextDocument(0x166abf795e0), parent's thread is QThread(0x166a9bb0fb0), current thread is QThread(0x166abf56000)

I think I know why this is happening, but do not know how to fix it.我想我知道为什么会这样,但不知道如何解决。 I presume that I should use PyQt5's own QThread class, but cannot get my head around how to do it.我认为我应该使用 PyQt5 自己的 QThread 类,但无法理解如何去做。 Currently, I will just run my three separate text based Python applications with each showing its output in its own window, but I would prefer a single GUI based application with all three incorporated.目前,我将只运行我的三个独立的基于文本的 Python 应用程序,每个应用程序在自己的窗口中显示其输出,但我更喜欢一个基于 GUI 的应用程序,其中包含所有三个。

The problem has nothing to do with the use of QThread or not.问题与是否使用QThread无关。 The problem is that the GUI elements (for example the QWidget, QTextDocument, etc) are not thread-safe so you should not modify them or create them in a different thread than the main one.问题是 GUI 元素(例如 QWidget、QTextDocument 等)不是线程安全的,因此您不应修改它们或在与主线程不同的线程中创建它们。 To emphasize my initial comment in my solution I will not use QThread but I will continue using threading but I will send the information to the main thread through signals(what if they are thread-safe):为了在我的解决方案中强调我最初的评论,我不会使用 QThread,但我会继续使用线程,但我会通过信号将信息发送到主线程(如果它们是线程安全的呢):

import sys, time
from threading import Thread

from PyQt5.QtCore import pyqtSignal, QObject
from PyQt5.QtWidgets import (
    QApplication,
    QMainWindow,
    QWidget,
    QPlainTextEdit,
    QHBoxLayout,
)


class Worker(QObject):
    messageChanged = pyqtSignal(str)

    def start(self, fn):
        Thread(target=self._execute, args=(fn,), daemon=True).start()

    def _execute(self, fn):
        fn(self)

    def write(self, message):
        self.messageChanged.emit(message)


def run1(worker):
    for i in range(20):
        worker.write(f"{i}\n")
        time.sleep(0.0125)


def run2(worker):
    for i in range(20):
        worker.write(f"{i}\n")
        time.sleep(0.0125)


def run3(worker):
    for i in range(20):
        worker.write(f"{i}\n")
        time.sleep(0.0125)


app = QApplication([sys.argv])
win = QMainWindow()

text_1 = QPlainTextEdit()
text_2 = QPlainTextEdit()
text_3 = QPlainTextEdit()

my_widget = QWidget()
my_widget.layout = QHBoxLayout()
my_widget.layout.addWidget(text_1)
my_widget.layout.addWidget(text_2)
my_widget.layout.addWidget(text_3)
my_widget.setLayout(my_widget.layout)

win.setCentralWidget(my_widget)

worker1 = Worker()
worker1.messageChanged.connect(text_1.appendPlainText)

worker2 = Worker()
worker2.messageChanged.connect(text_2.appendPlainText)

worker3 = Worker()
worker3.messageChanged.connect(text_3.appendPlainText)

worker1.start(run1)
worker2.start(run2)
worker3.start(run3)


win.show()

sys.exit(app.exec_())

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 PyQt5 QObject:无法为处于不同线程中的父级创建子级 - PyQt5 QObject: Cannot create children for a parent that is in a different thread QObject:无法为不同线程中的父级创建子级。 PyQt5 - QObject: Cannot create children for a parent that is in a different thread. PyQt5 使用pyqt5和sqlite的python程序出错,无法为不同线程中的父级创建子级 - Error with python program with pyqt5 and sqlite, Cannot create children for a parent that is in a different thread PyQt5 无法从线程更新进度条并收到错误“无法为不同线程中的父级创建子级” - PyQt5 cannot update progress bar from thread and received the error “Cannot create children for a parent that is in a different thread” PyQt多线程,无法为父级创建子级 - PyQt Multi Threading, Cannot create children for a parent PyQt4和flask:无法为处于不同线程中的父级创建子级 - PyQt4 & flask : Cannot create children for a parent that is in a different thread QObject:无法为处于不同线程中的父级创建子级。父级是QTextDocument,父级的线程是QThread,当前线程是QThread - QObject:Cannot create children for a parent that is in different thread.Parent is QTextDocument,parent's thread is QThread,current thread is QThread QObject::setParent:无法设置父级,新父级在 Python 中的不同线程中 - QObject::setParent: Cannot set parent, new parent is in a different thread in Python PyQt5:如何将QObject移动到主线程? - PyQt5: How to move a QObject to the main thread? Pyqt5 多线程错误:QObject::connect:无法排队 'QTextCursor' 类型的 arguments - Pyqt5 Multi-threading Error: QObject::connect: Cannot queue arguments of type 'QTextCursor'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM