我注意到有很多用户,包括我自己,他们并不完全掌握Qt中信号和插槽的概念。我希望对以下内容有所澄清:
#I have a function that runs as soon as the GUI is built, this takes the information from
#a list and puts it into a string which is then uploaded to a texbox. At the bottom of this
#loop, I want it to call a function in the parent thread via signals and slots, as
#recommended by other users.
class MainWindow(QtGui.QMainWindow):
#all the code needed to build the GUI
thread_mythread = threading.Thread(target = self.updateText, args = ())
thread_mythread.start()
def clearText(self):
self.TextEdit.clear()
def updateText(self):
self.trigger.connect(self.clearText)
while True:
self.trigger.emit()
NewString = list.pop(0)
#I think I may have to use append, as setText() is not safe outside of the parent thread
self.TextEdit.append(NewString)
虽然可能非常不正确,但我尝试使用信号。这是正确的方法吗?我也得到一个错误,说主窗口对象没有属性“触发器”,为什么会这样?
谢谢你。答案 0 :(得分:2)
您收到该错误的原因正是错误消息所描述的原因 - 您的班级中的任何位置都未定义信号trigger
。您需要在发射它之前定义它。
信号和插槽用于在不同对象之间进行通信。在您的示例中,您尝试从MainWindow
类中执行所有操作,并且不会与其他对象进行交互。您也只需要拨打connect()
一次电话。通常在实例化要连接在一起的对象后,在类构造函数或主函数中调用它。
查看http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html有关如何在PyQt中正确使用信号和插槽的一些示例。
对于线程,使用QThread而不是threading.Thread,因为它更好地与Qt框架集成。 This post显示了一些如何在PyQt中使用QThread的简单示例。第二种方法(使用moveToThread()
)被认为是创建新线程的最正确方法。
您遇到的问题的基本思路是:
另请注意:
答案 1 :(得分:2)
添加到@ user3419537的答案很好。一个非常快速的线程示例:
from PyQt4.QtCore import QObject, pyqtSlot, pyqtSignal, QThread, \
Q_ARG, Qt, QMetaObject
class MyWorker(QObject):
# define signal
clear = pyqtSignal()
update_text_signal = pyqtSignal(str) # passes a string back
finished = pyqtSignal()
def __init__(self, parent=None):
super(MyWorker, self).__init__(parent)
# Add functions etc.
@pyqtSlot(list)
def update_text(self, string_list):
#Intensive operation
self.clear.emit() # moved outside of while
while(True):
#This is infinite loop so thread runs forever
new_string = self.string_list.pop(0)
self.update_text_signal.emit(new_string) # Fixed this line
#Finished
self.finished.emit()
然后在您的MainWindow类中
self.my_thread = QThread()
self.handler = MyWorker()
self.handler.moveToThread(self.my_thread)
self.handler.clear.connect(self.clearText)
self.handler.update_text_signal.connect(self.update_line_edit)
self.handler.finished.connect(self.my_thread.quit)
# Start Thread
self.my_thread.start()
@pyqtSlot(str)
def update_line_edit(self, text):
self.TextEdit.append(text)
QMetaObject.invokeMethod(self.handler, 'update_text',
Qt.QueuedConnection,
Q_ARG(list, string_list))
您需要在应用程序关闭之前调用self.my_thread.quit()
以停止线程并避免错误:QThread: Destroyed while thread is still running
请阅读docs以获取QMetaObject.invokeMethod。