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

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

问题描述

我在 PyQt 中有一个带有函数 addImage(image_path) 的 GUI.很容易想象,当应该将新图像添加到 QListWidget 时会调用它.为了检测文件夹中的新图像,我使用带有 watchdogthreading.Thread 来检测文件夹中的文件更改,然后该线程调用 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.

使这个线程安全的最好和最简单的方法是什么?Q线程?信号/插槽?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.

推荐答案

我相信最好的方法是使用信号/槽机制.这是一个例子.(注意:请参阅下面的编辑,指出我的方法中可能存在的弱点.

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天全站免登陆