【问题标题】:QMessageBox to block parent while calculationQMessageBox 在计算时阻止父级
【发布时间】:2020-02-08 19:53:37
【问题描述】:

我想在计算时使用QMessageBox 阻止其父QDialog。我遇到了类似的东西,但这不起作用。

msgBox = QtWidgets.QMessageBox()
msgBox.setWindowTitle('Working ....')
msgBox.setText("Working, please wait ...")
msgBox.setStandardButtons(QtWidgets.QMessageBox.NoButton)
msgBox.exec_()

(doing some time consuming work)

msgBox.close()

出了什么问题,我该如何正确处理?

【问题讨论】:

    标签: python pyqt pyqt5 qmessagebox


    【解决方案1】:

    您必须在另一个线程中执行耗时的任务,并通过信号表明任务已完成执行。要关闭 QMessageBox,您必须使用 accept() 方法:

    import threading
    
    from PyQt5 import QtCore, QtWidgets
    
    
    class Worker(QtCore.QObject):
        started = QtCore.pyqtSignal()
        finished = QtCore.pyqtSignal()
    
        def execute(self, func, args):
            threading.Thread(target=self._execute, args=(func, args,), daemon=True).start()
    
        def _execute(self, func, args):
            self.started.emit()
            func(*args)
            self.finished.emit()
    
    
    def consuming_work(arg1, arg2):
        import time
    
        print(arg1, arg2)
        time.sleep(5)
        print("finish")
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
    
        msgBox = QtWidgets.QMessageBox()
        msgBox.setWindowTitle("Working ....")
        msgBox.setText("Working, please wait ...")
        msgBox.setStandardButtons(QtWidgets.QMessageBox.NoButton)
        worker = Worker(msgBox)
        worker.finished.connect(msgBox.accept)
        worker.execute(consuming_work, ["Stack", "Overflow"])
        msgBox.exec_()
    

    更新:

    import threading
    
    from PyQt5 import QtCore, QtWidgets
    
    
    class WorkerMessageBox(QtWidgets.QMessageBox):
        started = QtCore.pyqtSignal()
        finished = QtCore.pyqtSignal()
    
        def __init__(self, parent=None):
            super().__init__(parent)
            self.finished.connect(self.accept)
    
        def execute(self, func, args):
            threading.Thread(target=self._execute, args=(func, args,), daemon=True).start()
            return self.exec_()
    
        def _execute(self, func, args):
            self.started.emit()
            func(*args)
            self.finished.emit()
    
    
    def consuming_work(arg1, arg2):
        import time
    
        print(arg1, arg2)
        time.sleep(5)
        print("finish")
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
    
        msgBox = WorkerMessageBox()
        msgBox.setWindowTitle("Working ....")
        msgBox.setText("Working, please wait ...")
        msgBox.setStandardButtons(QtWidgets.QMessageBox.NoButton)
    
        msgBox.execute(consuming_work, ["Stack", "Overflow"])
    

    【讨论】:

    • 感谢您的回答。是否可以基于 QMessageBox 而不是泛型类来定义新类?我认为这会更容易使用,即 Worker.setText(...), Worker.setWindowsTitle(...)...
    • @Pygmalion 是的,有可能,我认为总的来说这应该是你工作的一部分,但这次我只会向你展示如何做到这一点。检查我的更新。
    • 我做的几乎和你一样,只是我把exec_放错了地方。但即使你的版本也不起作用,我得到AttributeError: 'PyQt5.QtCore.pyqtSignal' object has no attribute 'connect'。我猜我的实现出了点问题。
    • @Pygmalion 我刚刚在 Linux 中使用 PtQt5 5.14.1 测试了我的代码,它工作正常,我建议你复制我的代码而不修改它
    • 我发现了错误。只是在错误的地方输入一个命令,它不起作用。我很接近,但我自己可能做不到。
    猜你喜欢
    • 2011-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-19
    • 2022-01-17
    • 2016-07-28
    相关资源
    最近更新 更多