When I try to change the text of a text browser which is inside a scroll area I get this PyQt5 threading error:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTextDocument(0x212e3bb1f50), parent's thread is QThread(0x212e171e220), current thread is QThread(0x212e41dc7e0)
I assume it is because of the scroll area and that I don't have access to it from the thread I am trying to change this from and it works if I put the same bit of code...
filepath = "..."
with open(filepath, "r") as f:
contents = f.read()
#print(contents)
self.log_1.setText(contents)
(and yes I am aware that the filepath is "...", used for file security.)...inside the thread that the scrollarea is created inside it works completely fine.
The only thing I don't know is how to fix this. I think you might be able to inherit the thread to the scroll area in someway, idk.
My code, but simplified:
from PyQt5 import QtCore, QtGui, QtWidgets
from mcstatus import MinecraftServer
import threading
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1379, 523)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.scrollArea_1 = QtWidgets.QScrollArea(self.S1)
self.scrollArea_1.setGeometry(QtCore.QRect(0, 20, 981, 341))
self.scrollArea_1.setWidgetResizable(True)
self.scrollArea_1.setObjectName("scrollArea_1")
self.scrollAreaWidgetContents_1 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_1.setGeometry(QtCore.QRect(0, 0, 979, 339))
self.scrollAreaWidgetContents_1.setObjectName("scrollAreaWidgetContents_1")
self.log_1 = QtWidgets.QTextBrowser(self.scrollAreaWidgetContents_1)
self.log_1.setGeometry(QtCore.QRect(0, 0, 981, 341))
self.log_1.setMinimumSize(QtCore.QSize(981, 341))
self.log_1.viewport().setProperty("cursor",
QtGui.QCursor(QtCore.Qt.IBeamCursor))
self.log_1.setObjectName("log_1")
self.scrollArea_1.setWidget(self.scrollAreaWidgetContents_1)
def update1(self, MainWindow):
threading.Timer(0.2, self.update1, {MainWindow: MainWindow}).start()
ip = "..."
port = 25565 #Server 1
server = MinecraftServer(ip, port)
try:
filepath = "..."
with open(filepath, "r") as f:
contents = f.read()
#print(contents)
self.log_1.setText(contents)
except IOError as e:
self.StatusL_1.setText(self.translate("MainWindow", "<html><head/><body><p><span style=\" font-size:18pt;\">Status: Off</span></p></body></html>"))
else:
self.StatusL_1.setText(self.translate("MainWindow", "<html><head/><body><p><span style=\" font-size:18pt;\">Status: On</span></p></body></html>"))
You should not directly modify the GUI from another thread, one way to modify the GUI indirectly from another thread is to use the Qt signals:
import threading
from PyQt5 import QtCore, QtGui, QtWidgets
from mcstatus import MinecraftServer
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
# ...
class Worker(QtCore.QObject):
logged = QtCore.pyqtSignal(str)
statusChanged = QtCore.pyqtSignal(bool)
def start(self):
threading.Timer(0.2, self._execute, daemon=True).start()
def _execute(self):
threading.Timer(0.2, self._execute, daemon=True).start()
ip = "..."
port = 25565 # Server 1
server = MinecraftServer(ip, port)
try:
filepath = "..."
with open(filepath, "r") as f:
contents = f.read()
self.logged.emit(contents)
except IOError as e:
self.statusChanged.emit(False)
else:
self.statusChanged.emit(True)
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.worker = Worker()
self.worker.logged.connect(self.log_1.setText)
self.worker.statusChanged.connect(self.on_status_changed)
self.worker.start()
@QtCore.pyqtSlot(bool)
def on_status_changed(self, status):
text = '<html><head/><body><p><span style=" font-size:18pt;">Status: {}</span></p></body></html>'.format(
"On" if status else "Off"
)
self.StatusL_1.setText(text)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.