繁体   English   中英

信号和插槽PyQt澄清

[英]Signals and Slots PyQt clarification

我注意到,有很多用户(包括我自己)对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)

尽管可能非常错误,但是我尝试使用信号。 这是正确的方法吗? 我还收到一条错误消息,说“主窗口”对象没有属性“触发”,这是为什么?

谢谢。

收到该错误的原因正是错误消息所描述的原因-信号trigger尚未在您的课程中的任何位置定义。 您需要先定义它,然后才能发出它。

信号和插槽用于在不同对象之间进行通信。 在您的示例中,您尝试从MainWindow类中进行所有操作,并且与其他对象没有交互。 您还只需要调用一次connect() 在实例化要连接在一起的对象之后,通常可以在类构造函数中或从主函数中调用它。

看看http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html ,了解如何在PyQt中正确使用信号和插槽的一些示例。

对于线程,请使用QThread而不是threading.Thread,因为它可以更好地与Qt框架集成。 这篇文章展示了一些如何在PyQt中使用QThread的简单示例。 第二种方法(使用moveToThread() )被认为是创建新线程的最正确方法。

您遇到的这类问题的基本思路是:

  • 从主线程处理GUI操作
  • 在单独的线程中处理阻塞操作(在您的情况下为while循环)
  • 从辅助线程发出信号以调用主线程中的函数(插槽),反之亦然

另请注意:

  • 您不能从辅助线程调用QWidget的任何方法的后代
  • 如果您需要在线程之间传递信号,信号也可以发送数据

要添加到@ 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 self.my_thread.quit()

请阅读QMetaObject.invokeMethod的文档

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM