Stan Reduta
Stan Reduta

Reputation: 3492

Runtime progress status (like statusbar) in python

I'm trying to create simple progress status label for my Pyqt5 Python code and update it after every iteration of a loop in which a function does a bunch of stuff. The label I want to be updated is "status_label_counter". The below code only shows the part for creating labels and the exact place where I want to use the functionality I've mentioned.

    #initialisation code, etc...

    self.status_label_counter = QLabel()
    self.status_label_from = QLabel(' from: ')
    self.status_label_total = QLabel()
    status_hbox = QHBoxLayout()
    status_hbox.addStretch()
    status_hbox.addWidget(self.status_label_counter)
    status_hbox.addWidget(self.status_label_from)
    status_hbox.addWidget(self.status_label_total)
    status_hbox.addStretch()

    #bunch of other code...

    def create_ics(self):
        counter = 0
        self.status_label_total.setText(str(len(self.groups)))
        for group in self.groups:
            #does a bunch of stuff inside
            group_manager.create_calendar_for(self.rows, group, self.term)
            counter += 1
            #for console output
            print('iteration: ', counter)
            #trying to update status counter
            self.status_label_counter.setText(str(counter))

The problem is that I only see the update of both labels when the loop is done with the nested function. When I click a button that calls for "create_ics" function window becomes inactive for about 5 seconds, I see logs on console with count of iterations, but nothing happens in view.

Upvotes: 0

Views: 604

Answers (1)

zwer
zwer

Reputation: 25769

The view (Qt) is locked in your main thread and never gets its chance to process its event loop and thus redraw itself. If you really want to do it this way, call:

self.status_label_counter.repaint()

After you set the text (and if you have some complex layout measuring call QApplication.processEvents() instead).

However, much better option would be to run your create_ics() function in a separate thread leaving your main thread to deal with the view and Qt's event processing. You can do it either through standard Python's threading module, or using Qt's own QThread: https://nikolak.com/pyqt-threading-tutorial/ .

Upvotes: 1

Related Questions