创建新的线程来显示PyQt消息框几次是一个很好的实践



每次我想从主线程弹出消息框时,我都会尝试创建并运行一个新线程。想知道下面的代码是否会导致内存泄漏,甚至是一个好的做法。如果可以改进,如何改进?

class UIThread (threading.Thread):
    def __init__(self, message):
        print "UIThread init(). msg = " + message
        this_thread = threading.Thread.__init__(self)
        this_thread.daemon = True
        self.message = message
        self.qtapp = QApplication(sys.argv)
        self.w = QWidget()
    def run(self):
        print "UIThread running"
        result = QMessageBox.warning(self.w, 'WARNING', self.message, QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if result == QMessageBox.Yes:
            print 'Yes.'
        else:
            print 'No.'
        sys.exit(self.qtapp.exec_())
...
    messagebox = UIThread("Test")
    messagebox.start()      
....
    messagebox = UIThread("Test 2")
    messagebox.start()      
....
    # will pop up more message boxes throughout the program

不,这不是一个好的做法。您应该只从主线程执行GUI操作,包括显示消息框。使用信号和插槽与主线程通信,主线程可以显示消息框并为辅助线程提供响应。

这里有一个简单的例子,其中工作线程向主线程发送信号以显示消息框,然后检查responses字典中的消息框响应(基本字典操作是线程安全的)。此示例也适用于多个线程,因为响应是在线程名称下键入的。

from PyQt4 import QtCore, QtGui
import threading, time, sys

class Worker(QtCore.QObject):
    def __init__(self, app):
        super(Worker, self).__init__()
        self.app = app
    def do_stuff(self):
        thread_name = threading.current_thread().name
        self.app.responses[thread_name] = None
        self.app.showMessageBox.emit(thread_name,
                                     'information',
                                     'Hello',
                                     'Thread {} sent this message.'.format(thread_name))
        while self.app.responses[thread_name] is None:
            time.sleep(0.1)
        print 'Thread {} got response from message box: {}'.format(thread_name, self.app.responses[thread_name])

class MainWindow(QtGui.QMainWindow):
    showMessageBox = QtCore.pyqtSignal(str, str, str, str)
    def __init__(self, sys_argv):
        super(MainWindow, self).__init__(sys_argv)
        self.responses = {}
        self.showMessageBox.connect(self.on_show_message_box)
        self.worker = Worker(self)
        self.thread = QtCore.QThread()
        self.worker.moveToThread(self.thread)
        self.thread.started.connect(self.worker.do_stuff)
        self.thread.start()
    def on_show_message_box(self, id, severity, title, text):
        self.responses[str(id)] = getattr(QtGui.QMessageBox, str(severity))(self, title, text)

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    win = MainWindow(None)
    win.show()
    sys.exit(app.exec_())

相关内容

最新更新