Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

PyQt5 How to make updating progress bar when line from text is reading?



  • Hi, I want to do simple UI - click button opens file dialog, next choose text file and it's adding to list line by line. And this part works fine. When file has about 500k lines adding takes some time, so decided to make a progress bar. I was searching how to do this and here is my code:

    SIZE = 0
    VALUE = 0
    
    class External(QtCore.QThread):
        countChanged = QtCore.pyqtSignal(int)
        def run(self):
            while VALUE <= SIZE:
                time.sleep(0.01)
                counter = VALUE
                self.countChanged.emit(counter)
    
    class Ui_MainWindow(object):
            def setupUi(self, MainWindow):
                    \... some UI setup ...\
                    self.listView = QtWidgets.QListWidget()
                    self.pushButton = QtWidgets.QPushButton()
                    self.pushButton.clicked.connect(self.openFile)
                    self.progressBar = QtWidgets.QProgressBar()
            
              def openFile(self):
                    openfile = QFileDialog.getOpenFileName(self.pushButton, "Open File", "", "TXT (*.txt)")
                    global SIZE
                    global VALUE
                    SIZE = os.stat(openfile[0]).st_size
                    self.progressBar.setMinimum(0)
                    self.progressBar.setMaximum(SIZE)
                    if not openfile[0] == "":
                        with open(openfile[0], 'r') as f:
                            file_text = f.readlines()
                            self.calc = External()
                            self.calc.countChanged.connect(self.onCountChanged)
                            self.calc.start()
                        for line in file_text:
                            VALUE = VALUE + len(line)
                            self.listView.addItem(line)
                        VALUE = SIZE
              def onCountChanged(self, counter):
                    self.progressBar.setValue(counter)
    
    

    Text is added to list properly each time, but progress bar isn't updated, it looks as the progress value was added after loading the entire list to 100%.
    Why my progress bar doesn't work properly? What the code should look like?
    Thank you for your interest.


  • Lifetime Qt Champion

    Hi and welcome to the forums
    In a GUI app, there is an always running loop called the event loop.

    When you in your code make a long loop - you prevent this loop from running and
    the app won't get signals or events until your loop is finished. (you hang it, we say)

    That is why ProgressBar first can redraw after the loop.

    The ugly way of fixing this is calling
    app.processEvents()
    in the
    for line in file_text:
    as that allows paint messages and signals to have a chance to run.

    The more clean way is to use a Thread to do the reading.
    Like here
    https://stackoverflow.com/questions/34419926/how-to-make-qtgui-window-process-events-whenever-it-is-brought-forward-on-the-sc


  • Lifetime Qt Champion

    Hi and welcome to the forums
    In a GUI app, there is an always running loop called the event loop.

    When you in your code make a long loop - you prevent this loop from running and
    the app won't get signals or events until your loop is finished. (you hang it, we say)

    That is why ProgressBar first can redraw after the loop.

    The ugly way of fixing this is calling
    app.processEvents()
    in the
    for line in file_text:
    as that allows paint messages and signals to have a chance to run.

    The more clean way is to use a Thread to do the reading.
    Like here
    https://stackoverflow.com/questions/34419926/how-to-make-qtgui-window-process-events-whenever-it-is-brought-forward-on-the-sc


Log in to reply