How to generate an exception in a different thread

2019-03-01 20:24发布

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_()

enter image description here

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条回答
贪生不怕死
2楼-- · 2019-03-01 21:02

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_()
查看更多
登录 后发表回答