为什么 QDialog 在作业完成之前不显示任何小部件?

Why QDialog not shows any widgets until job completed?

我是 pyqt5 的新手,我尝试打开对话框并将一些文本推入该对话框

我的对话框包含一个明文、进度条和按钮

当我 运行 代码弹出对话框但未显示任何内容时,代码执行完成后显示所有小部件和文本

但我需要打开对话框并且我想要更新进度条

我的代码

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import (QDialog,QPlainTextEdit,QScrollArea,QProgressBar,QPushButton)
import sys
import time
class PrograssDialog():
    def ShowDialog(self,Dialogs):
        try:
            self.Pd=Dialogs
            self.Pd.setWindowTitle("Script Excution... ")
            self.Pd.resize(500,500)        
            self.ScrArea=QScrollArea(self.Pd)
            self.ScrArea.move(0,0)
            self.ScrArea.resize(500,300)
            self.TextArea=QPlainTextEdit(self.Pd)
            self.TextArea.move(0,0)
            self.TextArea.resize(500,300)
            self.TextArea.insertPlainText(str("Start : %s" % time.ctime())+"\n")
            self.Prograssbar=QProgressBar(self.Pd)
            self.Prograssbar.setGeometry(QtCore.QRect(0, 350, 450, 23))
            self.Prograssbar.setMaximum(100) 
            self.Cancelbutton=QPushButton("Cancel",self.Pd)
            self.Cancelbutton.setGeometry(QtCore.QRect(360, 400, 93, 28))
            self.Cancelbutton.clicked.connect(self.StopExcution)   
            self.Pd.show()
        except Exception as msg:
            import sys
            tb = sys.exc_info()[2]
            print("Error_analysis " + str(msg)+ str(tb.tb_lineno)) 
    def AddMessage(self,Message):
        self.TextArea.insertPlainText(str(Message)+"\n")
        # print("message added")
    def SetPercentage(self,Number):
        self.Prograssbar.setValue(Number)
        # print("percent added")
    def StopExcution(self):
        sys.exit()       
app = QApplication(sys.argv)
ui=PrograssDialog()
ui.ShowDialog(QDialog())
for i in range(100):
    ui.AddMessage("Hello")
    ui.SetPercentage(i)
    time.sleep(0.5)
sys.exit(app.exec_())  

您的代码存在各种问题,我会尽力解决所有问题。

  1. 您遇到的问题的主要原因是 no 阻塞函数(如 time.sleep)应该发生在主 Qt 线程中(这是显示 GUI 元素并允许与它们交互的线程);阻塞函数阻止 UI 正确绘制和刷新其内容,如果你想在特定的时间间隔进行操作,你必须使用 QTimer;

  2. 你不应该在这种情况下使用基本的 python 对象子类,特别是因为你只使用 one 对话框;您应该改为从 QDialog 子类化并实现

  3. 要“退出”您的程序,您不应使用 sys.exit(您已经在使用它),而应使用 QApplication.quit();另外,由于你一开始就已经导入了sys,所以在异常中就不需要再导入了;

  4. 函数和变量名应该大写;虽然您可以为自己的代码使用任何您想要的大小写样式,但通常(强烈建议)始终使用小写首字母,这也是与他人共享代码时应遵守的惯例,尤其是在 Whosebug 等问答网站上;阅读更多关于官方 Style Guide for Python Code;

  5. 始终避免儿童小部件的固定几何形状:其他人在他们的计算机上看到的可能与您在自己的计算机上看到的非常不同,并且您最终可能会得到一个无法使用的界面;改用布局管理器,以便小部件可以根据需要自行调整大小;

  6. 您添加了滚动区域但从未使用过;因为您对文本区域使用相同的几何形状,所以我相信您认为您正在使用它,但没有必要,因为文本区域已经 滚动区域;

为了实现您想要的效果,代码可能如下所示:

import time
from PyQt5 import QtCore, QtWidgets

class ProgressDialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)

        layout = QtWidgets.QVBoxLayout(self)

        self.textArea = QtWidgets.QPlainTextEdit()
        layout.addWidget(self.textArea)
        self.textArea.insertPlainText(str("Start : %s" % time.ctime())+"\n")
        self.textArea.setReadOnly(True)

        self.progressBar = QtWidgets.QProgressBar()
        layout.addWidget(self.progressBar)

        self.cancelButton = QtWidgets.QPushButton('Cancel')
        layout.addWidget(self.cancelButton)

        self.cancelButton.clicked.connect(QtWidgets.QApplication.quit)
        self.countTimer = QtCore.QTimer()
        self.countTimer.timeout.connect(self.timeout)

    def startCounter(self, maximum, sleepSeconds):
        self.progressBar.reset()
        self.progressBar.setMaximum(maximum)
        # QTimer interval is in milliseconds
        self.countTimer.setInterval(sleepSeconds * 1000)
        self.countTimer.start()

    def timeout(self):
        if self.progressBar.value() == self.progressBar.maximum():
            self.countTimer.stop()
            return
        self.setPercentage(self.progressBar.value() + 1)
        self.addMessage('Hello')

    def setPercentage(self, value):
        self.progressBar.setValue(value)

    def addMessage(self, message):
        self.textArea.insertPlainText(str(message) + '\n')


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    dialog = ProgressDialog()
    dialog.show()
    dialog.startCounter(100, .5)
    sys.exit(app.exec_())