我在PyQt中有一个带有功能的GUI addImage(image_path)。容易想象,当新图像应添加到QListWidget中时被调用。为了检测文件夹中的新图像,我使用了threading.Threadwithwatchdog来检测文件夹中的文件更改,然后该线程addImage直接调用。
addImage(image_path)
threading.Thread
watchdog
addImage
QPixmap出于线程安全的原因,这会产生不应在gui线程之外调用的警告。
QPixmap
使此线程安全的最佳和最简单的方法是什么?QThread?信号/插槽?QMetaObject.invokeMethod?我只需要从线程传递一个字符串到addImage。
我相信最好的方法是使用信号/插槽机制。这是一个例子。(注意:请参阅下面的 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进行线程安全通信的几种方法进行比较。我会深入研究问题,明天再做:-)