问题
good night I am trying to generate an exception in this example code, the exception of generates if at the time of changing the text in the QLineEdit the text could not be converted into a number.
However, when I'm running, I get an error and the program stops
error:
QObject::setParent: Cannot set parent, new parent is in a different thread
this is the code:
from PyQt5.QtWidgets import QMainWindow, QApplication, QMessageBox
from PyQt5 import QtCore
from PyQt5 import uic
import threading
class TheThread(threading.Thread):
def __init__(self,text):
threading.Thread.__init__(self)
self.tx = text
def run(self):
try:
print(int(self.tx),"number")
except:
QMessageBox.critical(None,"Error","Error ",QMessageBox.Ok)
class Principal(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
uic.loadUi("test.ui",self)
self.lineEdit.textChanged.connect(lambda:self.evalNumeros(self.lineEdit.text()))
@QtCore.pyqtSlot(str)
def evalNumeros(self,texto):
print(texto)
try:
threadClass = TheThread(texto)
threadClass.start()
except:
print("error")
app = QApplication([])
p = Principal()
p.show()
app.exec_()
this is the filu.ui for this code test.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>641</width>
<height>479</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QLineEdit" name="lineEdit">
<property name="geometry">
<rect>
<x>200</x>
<y>100</y>
<width>191</width>
<height>20</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="yes">
<property name="geometry">
<rect>
<x>170</x>
<y>150</y>
<width>111</width>
<height>31</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">color:white;
background:red;</string>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QLabel" name="no">
<property name="geometry">
<rect>
<x>300</x>
<y>150</y>
<width>111</width>
<height>31</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">color:white;
background:green;</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>641</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
回答1:
The problem is that you can not invoke the GUI directly in another thread, so there are 2 possible solutions: use a signal to invoke a method that shows the QMessageBox or use QMetaObject.invokeMethod to invoke that method, in this case I will use the second since the first one there are many examples in SO.
from PyQt5 import QtCore, QtWidgets, uic
from PyQt5 import uic
import threading
class TheThread(threading.Thread):
def __init__(self, text, obj):
threading.Thread.__init__(self)
self.tx = text
self.obj = obj
def run(self):
try:
print(int(self.tx),"number")
except:
QtCore.QMetaObject.invokeMethod(self.obj, "onError",
QtCore.Qt.QueuedConnection,
QtCore.Q_ARG(str, "Error"),
QtCore.Q_ARG(str, "Error"))
class Principal(QtWidgets.QMainWindow):
def __init__(self):
super(Principal, self).__init__()
uic.loadUi("test.ui",self)
self.lineEdit.textChanged.connect(self.evalNumeros)
@QtCore.pyqtSlot(str)
def evalNumeros(self,texto):
threadClass = TheThread(texto, self)
threadClass.start()
@QtCore.pyqtSlot(str, str)
def onError(self, title, text):
QtWidgets.QMessageBox.critical(None, title, text, QtWidgets.QMessageBox.Ok)
app = QtWidgets.QApplication([])
p = Principal()
p.show()
app.exec_()
来源:https://stackoverflow.com/questions/54016884/how-to-generate-an-exception-in-a-different-thread