-1

im new to pyqt5,i tried to open dialog and push some text into that dialog

my dialog contain one plaintext ,progressbar and pushbutton

when i run the code its popup the dialog but not shown any thing ,after code execution completes its showing all the widgets and with text

but i need to open the dialog and i want update progress bar

My code

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
    Your `for` loop blocks the Qt event loop. Hence no changes will be visible until the `for` loop completes and the `app.exec()` statement executes. If you need timed updates consider using a [`QTimer`](https://doc.qt.io/qt-5/qtimer.html) instead. – G.M. Aug 01 '20 at 12:35

1 Answers1

2

There are various problems with your code, I'll try to address all of them.

  1. The main reason for the issue you are facing is that no blocking functions (like time.sleep) should happen in the main Qt thread (which is the thread that shows the GUI elements and allow interactions with them); blocking functions prevent the UI to correctly draw and refresh its contents, if you want to do an operation at specific intervals, you have to use a QTimer;

  2. You should not use a basic python object subclass for this kind of situations, especially since you're only using just one dialog; you should subclass from QDialog instead and implement

  3. To "exit" your program you should not use sys.exit (you are already using it), but use QApplication.quit() instead; also, since you already imported sys at the beginning, there's no need to import it again in the exception;

  4. Function and variable names should not be capitalized; while you can use any casing style you want for your own code, it's common (and highly suggested) practice to always use lowercase initials, and it's also a convention you should stick to when sharing code with others, especially on Q&A sites like StackOverflow; read more on the official Style Guide for Python Code;

  5. Always avoid fixed geometries for children widgets: what others see on their computers will probably be very different from what you see on yours, and you might end up with an unusable interface; use layout managers instead, so that the widgets can resize themselves if required;

  6. You added a scroll area but you never use it; since you're using the same geometry for the text area I believe that you thought you were using for that, but there's no need as the text area already is a scroll area;

Here is how the code could look like in order to achieve what you want:

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_())
musicamante
  • 41,230
  • 6
  • 33
  • 58