PyQT线程化的最简单方法 [英] Simplest way for PyQT Threading

查看:126
本文介绍了PyQT线程化的最简单方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a GUI in PyQt with a function addImage(image_path). Easy to imagine, it is called when a new image should be added into a QListWidget. For the detection of new images in a folder, I use a threading.Thread with watchdog to detect file changes in the folder, and this thread then calls addImage directly.

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

This yields the warning that QPixmap shouldn't be called outside the gui thread, for reasons of thread safety.

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

What is the best and most simple way to make this threadsafe? QThread? Signal / Slot? QMetaObject.invokeMethod? I only need to pass a string from the thread to addImage.

推荐答案

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

I believe the best approach is using the signal/slot mechanism. Here is an example. (Note: see the EDIT below that points out a possible weakness in my approach).

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应用程序代码中,应该创建新的线程,为其提供正确的回调函数,然后使其运行.

In your GUI application code, you should create the new Thread, give it the right callback function, and make it run.

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

编辑

先生. three_pineapples和Brendan Abel先生指出了我的方法中的一个缺点.实际上,该方法在这种特定情况下效果很好,因为您可以直接生成/发射信号.当处理按钮和小部件上的内置Qt信号时,您应该采用另一种方法(如Brendan Abel先生的回答中所指定).

Mr. three_pineapples and Mr. Brendan Abel pointed out a weakness in my approach. Indeed, the approach works fine for this particular case, because you generate / emit the signal directly. When you deal with built-in Qt signals on buttons and widgets, you should take another approach (as specified in the answer of Mr. Brendan Abel).

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

Mr. three_pineapples adviced me to start a new topic in StackOverflow to make a comparison between the several approaches of thread-safe communication with a GUI. I will dig into the matter, and do that tomorrow :-)

这篇关于PyQT线程化的最简单方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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