猿问

Python-父代和多线程问题

我正在学习PyQT和多线程,我想在这里需要帮助。在我的代码中,我有Tool一个class和一个thread TaskThread。从线程中,我调用一个函数dummy_function,该函数执行进度条在GUI中显示的过程。

dummy_function完成后,我想在GUI打印一条消息,通过调用self.outputText.setText("Hello")。但是,出现以下错误:

AttributeError:'TaskThread'对象没有属性'outputText'

我尝试的第一件事是将以下行添加到我的onStart函数中:


...

self.myLongTask.output_dt = self.outputText

...

然后,在中TaskThread,我dummy_function通过以下方式更改调用:


...

dummy_function(self, start_datetime_unix, end_datetime_unix, self.output_dt) 

...

最后,我通过添加以下新参数来更改我的dummy_function:


def dummy_function(self, start_datetime_unix, end_datetime_unix, output_text): 

    # Dummy function, just to simulate a task. It takes parameters just for testing.

    result = start_datetime_unix * end_datetime_unix 


    # Pre-steps for mapping from one range to other (progress-bar)

    OldMax = 99999

    OldMin = 1

    NewMax = 100

    NewMin = 1


    OldRange = (OldMax - OldMin)

    NewRange = (NewMax - NewMin)    


    u = 1

    for i in range (OldMax):

        u = i*2


        OldValue = i

        print OldValue

        NewValue = (((OldValue - OldMin) * NewRange) / OldRange) + NewMin

        print "NEW VALUE: ", NewValue


        self.emit(QtCore.SIGNAL('CPU_VALUE'), NewValue)


    output_text.setText("Hello")

现在,到达终点时,程序将关闭,并显示以下错误:


QObject:无法为处于不同线程中的父级创建子级。(父母是QTextDocument(0xf13a60),父母的线程是QThread(0xc6f180),当前线程是TaskThread(0xee0740)


为了尝试该程序,我升级了GUInterface,因此如有必要,您可以尝试一下。


翻翻过去那场雪
浏览 171回答 1
1回答

收到一只叮咚

您得到的第一个是由于TaskThread没有outputText属性而引起的,并且您的解决方案在某种程度上是正确的,因为它解决了第一个问题,但是还有另一个问题,Qt禁止从另一个生成该线程的线程直接更新该GUI。问题 。Qt表示如果您要使用其他线程的信息更新GUI,您必须使用信号或信号QMetaObject,在这种情况下,我将通过创建一个signal被调用来解决它textChanged,它将与的setText()方法连接outputText。另一方面,我看到您使用的是旧的连接样式:self.connect(self.myLongTask, QtCore.SIGNAL('CPU_VALUE'), self.onProgress)尽管不再建议您仍然可以使用该样式,但最好还是使用新语法。最后,连接到信号的功能称为插槽,因此建议使用装饰器@QtCore.pyqtSlot(...),此方法可最大程度地减少资源消耗。import sysimport datetimeimport timefrom PyQt4 import QtCore, QtGui, uicfrom PyQt4.QtCore import *from PyQt4.QtGui import *# Link to GUIqtCreatorFile = "GUInterface.ui"Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)def time_converter_to_unix(start_datetime, end_datetime):&nbsp; &nbsp; # Convert QTimeEdit to UNIX Timestamp (int, msec included), and then to float&nbsp; &nbsp; start_datetime_unix_int = start_datetime.toMSecsSinceEpoch ()&nbsp; &nbsp; start_datetime_unix = (float(start_datetime_unix_int) / 1000)&nbsp; &nbsp; end_datetime_unix_int = end_datetime.toMSecsSinceEpoch ()&nbsp; &nbsp; end_datetime_unix = (float(end_datetime_unix_int) / 1000)&nbsp; &nbsp; return start_datetime_unix, end_datetime_unixdef dummy_function(self, start_datetime_unix, end_datetime_unix):&nbsp;&nbsp; &nbsp; # Dummy function, just to simulate a task. It takes parameters just for testing.&nbsp; &nbsp; result = start_datetime_unix * end_datetime_unix&nbsp;&nbsp; &nbsp; # Pre-steps for mapping from one range to other (progress-bar)&nbsp; &nbsp; OldMax = 99999&nbsp; &nbsp; OldMin = 1&nbsp; &nbsp; NewMax = 100&nbsp; &nbsp; NewMin = 1&nbsp; &nbsp; OldRange = (OldMax - OldMin)&nbsp; &nbsp; NewRange = (NewMax - NewMin)&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; u = 1&nbsp; &nbsp; for i in range (OldMax):&nbsp; &nbsp; &nbsp; &nbsp; u = i*2&nbsp; &nbsp; &nbsp; &nbsp; OldValue = i&nbsp; &nbsp; &nbsp; &nbsp; print(OldValue)&nbsp; &nbsp; &nbsp; &nbsp; NewValue = (((OldValue - OldMin) * NewRange) / OldRange) + NewMin&nbsp; &nbsp; &nbsp; &nbsp; print("NEW VALUE: ", NewValue)&nbsp; &nbsp; &nbsp; &nbsp; self.cpuValueChanged.emit(NewValue)&nbsp; &nbsp; self.textChanged.emit("Hello")class Tool(QtGui.QMainWindow, Ui_MainWindow):&nbsp; &nbsp; def __init__(self, parent = None):&nbsp; &nbsp; &nbsp; &nbsp; # Setting-ip UI&nbsp; &nbsp; &nbsp; &nbsp; QtGui.QMainWindow.__init__(self)&nbsp; &nbsp; &nbsp; &nbsp; Ui_MainWindow.__init__(self)&nbsp; &nbsp; &nbsp; &nbsp; self.setupUi(self)&nbsp; &nbsp; &nbsp; &nbsp; # Button Action&nbsp; &nbsp; &nbsp; &nbsp; self.runButton.clicked.connect(self.onStart)&nbsp; &nbsp; &nbsp; &nbsp; # Progress Bar and Label. At the begining, the bar is at 0&nbsp; &nbsp; &nbsp; &nbsp; self.progressBar.setValue(0)&nbsp; &nbsp; &nbsp; &nbsp; self.progressBar.setRange(0,100)&nbsp; &nbsp; &nbsp; &nbsp; self.resultLabel.setText("Waiting...")&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; ####################################&nbsp; &nbsp; &nbsp; &nbsp; #TEST: Thread for progress bar&nbsp; &nbsp; &nbsp; &nbsp; self.myLongTask = TaskThread()&nbsp; &nbsp; &nbsp; &nbsp; self.myLongTask.cpuValueChanged.connect(self.progressBar.setValue)&nbsp; &nbsp; &nbsp; &nbsp; self.myLongTask.textChanged.connect(self.outputText.setText)&nbsp; &nbsp; &nbsp; &nbsp; self.myLongTask.taskFinished.connect(self.onFinished)&nbsp; &nbsp; &nbsp; &nbsp; ####################################&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; @QtCore.pyqtSlot()&nbsp; &nbsp; def onStart(self):&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; self.progressBar.reset()&nbsp; &nbsp; &nbsp; &nbsp; self.resultLabel.setText("In progress...")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; print("(onStart)In progress mode executed")&nbsp; &nbsp; &nbsp; &nbsp; print("(onStart)INITIALIZE THREAD")&nbsp; &nbsp; &nbsp; &nbsp; self.myLongTask.start()&nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; print("(onStart)THREAD EXECUTED")&nbsp; &nbsp; &nbsp; &nbsp; self.myLongTask.start_dt = self.startTime.dateTime() # <----&nbsp; &nbsp; &nbsp; &nbsp; self.myLongTask.end_dt = self.endTime.dateTime()&nbsp; &nbsp; &nbsp;# <----&nbsp; &nbsp; &nbsp;&nbsp; &nbsp; @QtCore.pyqtSlot()&nbsp; &nbsp; def onFinished(self):&nbsp; &nbsp; &nbsp; &nbsp; # Stop the pulsation when the thread has finished&nbsp; &nbsp; &nbsp; &nbsp; print("(onFinished) executed")&nbsp; &nbsp; &nbsp; &nbsp; self.progressBar.setRange(0,1)&nbsp; &nbsp; &nbsp; &nbsp; self.progressBar.setValue(1)&nbsp; &nbsp; &nbsp; &nbsp; self.resultLabel.setText("Done")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;class TaskThread(QtCore.QThread):&nbsp; &nbsp; cpuValueChanged = QtCore.pyqtSignal(int)&nbsp;&nbsp;&nbsp; &nbsp; taskFinished = QtCore.pyqtSignal()&nbsp; &nbsp; textChanged = QtCore.pyqtSignal(str)&nbsp; &nbsp; def __del__(self):&nbsp; &nbsp; &nbsp; &nbsp; self.wait()&nbsp; &nbsp; def run(self):&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; # First, we read the times from the QDateTime elements in the interface&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; print("Getting times...")&nbsp; &nbsp; &nbsp; &nbsp; start_datetime_unix, end_datetime_unix = time_converter_to_unix(self.start_dt, self.end_dt)&nbsp; &nbsp; &nbsp; &nbsp; # Then, we put these values in my_function&nbsp; &nbsp; &nbsp; &nbsp; print("Executing function...")&nbsp; &nbsp; &nbsp; &nbsp; dummy_function(self, start_datetime_unix, end_datetime_unix)&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; # To finish, we execute onFinished.&nbsp; &nbsp; &nbsp; &nbsp; print("Finishing thread...")&nbsp; &nbsp; &nbsp; &nbsp; self.taskFinished.emit()def main():&nbsp; &nbsp; app = QtGui.QApplication(sys.argv)&nbsp; &nbsp; window = Tool()&nbsp; &nbsp; window.show()&nbsp; &nbsp; sys.exit(app.exec_())if __name__ == '__main__':&nbsp; &nbsp; main()
随时随地看视频慕课网APP

相关分类

Python
我要回答