信号和插槽 PyQt 澄清 [英] Signals and Slots PyQt clarification

查看:35
本文介绍了信号和插槽 PyQt 澄清的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到有很多用户,包括我自己,不太了解 Qt 中信号和槽的概念.我希望得到一些关于以下方面的澄清:

#我有一个函数,它在构建 GUI 后立即运行,它从以下位置获取信息#a list 并将其放入一个字符串中,然后将其上传到 texbox.在这个底部#loop,我希望它通过信号和槽调用父线程中的函数,如#其他用户推荐.

class MainWindow(QtGui.QMainWindow):#构建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)为真:self.trigger.emit()NewString = list.pop(0)#我想我可能必须使用 append,因为 setText() 在父线程之外是不安全的self.TextEdit.append(NewString)

虽然可能非常不正确,但我尝试使用信号.这是正确的方法吗?我还收到一条错误消息,指出主窗口对象没有触发器"属性,这是为什么?

谢谢.

解决方案

添加到@user3419537 好答案.一个非常快速的线程示例:

from PyQt4.QtCore import QObject, pyqtSlot, pyqtSignal, QThread, \Q_ARG、Qt、QMetaObject类 MyWorker(QObject):# 定义信号清除 = pyqtSignal()update_text_signal = pyqtSignal(str) # 传回一个字符串完成 = pyqtSignal()def __init__(self, parent=None):super(MyWorker, self).__init__(parent)# 添加函数等@pyqtSlot(列表)def update_text(self, string_list):#密集操作self.clear.emit() # 移到 while 之外而(真):#这是无限循环所以线程永远运行new_string = self.string_list.pop(0)self.update_text_signal.emit(new_string) # 修复了这一行#完成的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)# 开始线程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(列表,字符串列表))

您需要在应用程序关闭之前调用 self.my_thread.quit() 以停止线程并避免错误:QThread: Destroyed while thread is still running

请阅读 QMetaObject.invokeMethod 的文档.>

I have noticed that there are a lot of users, myself included, who don't quite grasp the concept of signals and slots in Qt. I was hoping to get some clarification on the following:

#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)

Although probably terribly incorrect, I attempt to use signals. Is this the proper way to do it? I also get an error that says that the Main Window object has no attribute "trigger",why is this?

thank you.

解决方案

To add to @user3419537 good answer. A very quick threading example:

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()

Then in your MainWindow class

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))

You will need to call self.my_thread.quit() before your application closes to stop the thread and avoid the error: QThread: Destroyed while thread is still running

Please read docs for QMetaObject.invokeMethod.

这篇关于信号和插槽 PyQt 澄清的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆