创建用于显示PyQt消息框的新线程几次是一个好习惯吗?

时间:2015-12-08 23:37:11

标签: python pyqt4

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

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

1 个答案:

答案 0 :(得分:1)

不,这不是好习惯。你应该只从主线程做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_())