PyQT线程化的最简单方法

发布于 2021-01-29 15:02:08

我在PyQt中有一个带有功能的GUI
addImage(image_path)。容易想象,当新图像应添加到QListWidget中时被调用。为了检测文件夹中的新图像,我使用了threading.Threadwithwatchdog来检测文件夹中的文件更改,然后该线程addImage直接调用。

QPixmap出于线程安全的原因,这会产生不应在gui线程之外调用的警告。

使此线程安全的最佳和最简单的方法是什么?QThread?信号/插槽?QMetaObject.invokeMethod?我只需要从线程传递一个字符串到addImage

关注者
0
被浏览
88
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    我相信最好的方法是使用信号/插槽机制。这是一个例子。(注意:请参阅下面的 EDIT ,指出我的方法可能存在的缺陷)。

    from PyQt4 import QtGui
    from PyQt4 import QtCore
    
    # Create the class 'Communicate'. The instance
    # from this class shall be used later on for the
    # signal/slot mechanism.
    
    class Communicate(QtCore.QObject):
        myGUI_signal = QtCore.pyqtSignal(str)
    
    ''' End class '''
    
    
    # Define the function 'myThread'. This function is the so-called
    # 'target function' when you create and start your new Thread.
    # In other words, this is the function that will run in your new thread.
    # 'myThread' expects one argument: the callback function name. That should
    # be a function inside your GUI.
    
    def myThread(callbackFunc):
        # Setup the signal-slot mechanism.
        mySrc = Communicate()
        mySrc.myGUI_signal.connect(callbackFunc)
    
        # Endless loop. You typically want the thread
        # to run forever.
        while(True):
            # Do something useful here.
            msgForGui = 'This is a message to send to the GUI'
            mySrc.myGUI_signal.emit(msgForGui)
            # So now the 'callbackFunc' is called, and is fed with 'msgForGui'
            # as parameter. That is what you want. You just sent a message to
            # your GUI application! - Note: I suppose here that 'callbackFunc'
            # is one of the functions in your GUI.
            # This procedure is thread safe.
    
        ''' End while '''
    
    ''' End myThread '''
    

    在GUI应用程序代码中,应该创建新的Thread,为其提供正确的回调函数,然后使其运行。

    from PyQt4 import QtGui
    from PyQt4 import QtCore
    import sys
    import os
    
    # This is the main window from my GUI
    
    class CustomMainWindow(QtGui.QMainWindow):
    
        def __init__(self):
            super(CustomMainWindow, self).__init__()
            self.setGeometry(300, 300, 2500, 1500)
            self.setWindowTitle("my first window")
            # ...
            self.startTheThread()
    
        ''''''
    
        def theCallbackFunc(self, msg):
            print('the thread has sent this message to the GUI:')
            print(msg)
            print('---------')
    
        ''''''
    
    
        def startTheThread(self):
            # Create the new thread. The target function is 'myThread'. The
            # function we created in the beginning.
            t = threading.Thread(name = 'myThread', target = myThread, args = (self.theCallbackFunc))
            t.start()
    
        ''''''
    
    ''' End CustomMainWindow '''
    
    
    # This is the startup code.
    
    if __name__== '__main__':
        app = QtGui.QApplication(sys.argv)
        QtGui.QApplication.setStyle(QtGui.QStyleFactory.create('Plastique'))
        myGUI = CustomMainWindow()
        sys.exit(app.exec_())
    
    ''' End Main '''
    

    编辑

    三菠萝先生和布伦丹·阿贝尔先生指出了我的作风。确实,该方法在这种特定情况下效果很好,因为您可以直接生成/发射信号。当处理按钮和小部件上的内置Qt信号时,您应该采用另一种方法(如Brendan
    Abel先生的回答中所指定)。

    three_pineapples先生建议我在StackOverflow中启动一个新主题,以便与GUI进行线程安全通信的几种方法进行比较。我会深入研究问题,明天再做:-)



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看