How to generate an exception in a different thread

偶尔善良 提交于 2019-12-20 04:25:27

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!