【问题标题】:Qthread isn't working Not returning signalsQthread 不工作 不返回信号
【发布时间】:2022-07-07 01:58:25
【问题描述】:

我有这个 WorkerSignals 类,用于将信号与 Qthread 类工作者连接,SaveToExcel() 是我曾经在 Qthread 中运行的函数。

class WorkerSignals(QObject):
    finished = pyqtSignal()
    error = pyqtSignal(tuple)
    result = pyqtSignal(object)
    progress = pyqtSignal(int)

    
class Worker(QThread):
    def __init__(self,query,filename,choices,fileExtension,iterativeornot):
        super(Worker,self).__init__()
        self.signals = WorkerSignals()
        self.query =query
        self.filename = filename
        self.choices = choices
        self.fileExtension = fileExtension
        self.iterativeornot =iterativeornot
   

    @pyqtSlot()
    def run(self):
         
        try:
            SaveToExcel(self.query,self.filename,self.choices,self.fileExtension,self.iterativeornot)
        except:
            self.signals.result.emit(1)
        finally:
            self.signals.finished.emit()
       

这是我用来创建具有 ui 的 Qwidget 的类

class AnotherWindow(QWidget):
    
    def __init__(self,windowname):
        super().__init__()
        self.layout = QVBoxLayout()
        self.label = QLabel()
        self.setWindowTitle(windowname)
        self.setWindowIcon(QIcon(os.path.join(basedir,'./images/import.png')))
        self.setFixedSize(460,440)
        self.layout.addWidget(self.label)
        
        # Query
        self.textinput = QPlainTextEdit()
        self.layout.addWidget(self.textinput)
        
        self.qhboxlayout1 = QHBoxLayout()
        self.IterativeRadiobtn1 = QRadioButton('All Locations')
        self.IterativeRadiobtn2 = QRadioButton('Current Locations')
        self.IterativeRadiobtn2.setChecked(True)
       
        self.qhboxlayout1.addWidget(self.IterativeRadiobtn1)
        self.qhboxlayout1.addWidget(self.IterativeRadiobtn2)
        
        self.layout.addLayout(self.qhboxlayout1)
        
        # Check boxes
        self.c1 = QCheckBox("sc",self)
        self.c2 = QCheckBox("ad",self)
        self.c3 = QCheckBox("sr",self)
        self.c4 = QCheckBox("fc",self)
        
        self.hboxlayoutchoices = QHBoxLayout()
        
    
        #adding checkboxes to layout
        self.checkboxlist = [self.c1,self.c2,self.c3,self.c4]
        for cbox in self.checkboxlist:
            self.hboxlayoutchoices.addWidget(cbox)
        self.layout.addLayout(self.hboxlayoutchoices)

        # filename 
        self.filename = QLineEdit()
        self.layout.addWidget(self.filename)
            
        # Combo box to show the filetype which need to be saved
        self.extensions = QComboBox()
        self.combodict = {'Excel 97-2003 Workbook (*.xls)':'xls','CSV UTF-8 (Comma delimited) (*.csv)':'csv'}
        self.extensions.addItems(self.combodict)
        self.layout.addWidget(self.extensions)
        
        # import button
        self.exportBtn = QPushButton('Import')
        self.layout.addWidget(self.exportBtn)    
        
        #import function when button clicked  
        self.exportBtn.clicked.connect(self.IMPORT)   
        
        #setting layout
        self.setLayout(self.layout)
    
    def RadioButtonCheck(self):
        if self.IterativeRadiobtn1.isChecked():
            return True
        if self.IterativeRadiobtn2.isChecked():
            return False
        
        

    def IMPORT(self):
        self.cboxlist = []
        for cbox in self.checkboxlist:
            if cbox.isChecked():
                self.cboxlist.append(cbox.text())
        
        self.textinput.setReadOnly(True)
        self.filename.setReadOnly(True)
        self.exportBtn.setDisabled(True)  
          
        self.saveFilename = self.filename.text()
        self.text = self.textinput.toPlainText()
        self.inputextension = self.extensions.currentText()
        self.getvalue = self.combodict.get(self.inputextension)
        self.truorfalse = self.RadioButtonCheck()
       
        # self.queryThread = threading.Thread(target=SaveToExcel,args=(self.text,self.saveFilename,self.cboxlist,self.getvalue,self.truorfalse))
        # self.queryThread.start()
        self.worker = Worker(self.text,self.saveFilename,self.cboxlist,self.getvalue,self.truorfalse)
        self.worktherad = QThread()
        self.worker.moveToThread(self.worktherad)
        self.worktherad.started.connect(self.worker.run)
        self.worktherad.finished.connect(self.complete)
        self.worktherad.start()
       
    def complete(self):
        self.msg = QMessageBox()
        self.msg.setWindowTitle("Status")
        self.msg.setText("Import Done")
        self.msg.exec()
        self.textinput.setReadOnly(False)
        self.filename.setReadOnly(False)
        self.exportBtn.setDisabled(False)
        self.exportBtn.setText("Import Again")
   

但是当我单击导入按钮时,该函数不会运行并且什么也不做,我对 Qthreading 没有很好的了解,但是当我使用 python 默认 threading 时,该函数将运行并导入数据。关于如何为SaveToExcel 函数实现 Qthreading,我仍然没有很清楚的想法。

【问题讨论】:

  • 首先,QThread 继承自 QObject,因此制作内部“信号”对象是没有意义的,只需将信号添加到您的子类中即可。然后,创建一个 QThread 并将其移动到另一个 QThread 再次毫无意义,只需使用 that 实例。最后,移除finished 信号,因为QThread 已经拥有它并且会在run() 返回时发出它。最后一件事:只有常量的名称应该全部大写;由于import 是受保护的关键字,因此只需使用更好 且更具描述性的名称,例如importExcel

标签: python multithreading pyqt pyqt5 qthread


【解决方案1】:
self.worker = Worker(self.text,self.saveFilename,self.cboxlist,self.getvalue,self.truorfalse)

在这一行中,您可能应该传递父字段,并且您应该在 Worker __init__ 方法中接受父字段并将其传递给 super 调用 (所以一旦它的父对象被删除,线程将自动销毁)

Worker 类已经是QThread,您无需创建另一个QThread 并移动它..

您应该只运行 self.worker by self.worker.start()

不要忘记将那些Worker 信号连接到有效的pyqtSlot,如果可能的话,在启动self.worker 线程之前连接它们

更新的代码片段

        self.worker = Worker(parent, self.text,self.saveFilename,self.cboxlist,self.getvalue,self.truorfalse) # Accept parent in __init__ method of Worker
        self.worktherad.finished.connect(self.complete)
        self.worktherad.start()

并且还通过添加装饰器QtCore.pyqtSlot() 使complete 成为pyqtSlot 函数

【讨论】:

    猜你喜欢
    • 2017-05-22
    • 2015-11-30
    • 1970-01-01
    • 1970-01-01
    • 2012-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多