3

I am building a tiny tool that does file operations at session startup. In order to make sure the user has a visual feedback, I want to associate it with a progress bar.

Here I am so far:

import sys
import time
from PySide.QtGui import *


class ProgressWindowWidget(QWidget):
    def __init__(self, parent=None):
        super(ProgressWindowWidget, self).__init__()

        self.init_ui()

    def init_ui(self):
        self.setGeometry(500, 500, 600, 100)
        self.setWindowTitle('Progress')

        self.layout_ = QGridLayout()
        self.setLayout(self.layout_)

        self.progress_bar = QProgressBar()
        self.layout_.addWidget(self.progress_bar, 0, 0, 1, 1)

    def my_operations(self):
        print('do something 1')
        time.sleep(2)
        print('do something 2')
        time.sleep(2)
        print('do something 3')
        time.sleep(2)


def main():
    app = QApplication(sys.argv)
    progress_window = ProgressWindowWidget()
    progress_window.show()
    progress_window.my_operations()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

My problem is that my_operations is executed first and then my GUI is loaded. I'd like to execute my_operations only when the progress bar is loaded, so I can update it.

According to this, it has something to do with the exec_ main loop, but there's obviously something I don't understand here because I am calling my_operations after show.

Needless to say, I'm a beginner. Does anyone have an idea? Cheers

E. Earl
  • 134
  • 2
  • 13
Munshine
  • 402
  • 3
  • 14

1 Answers1

2

Every GUI lives in an event loop that allows you to handle events of the user, the OS, etc. such as the mouse, the keyboard, etc., so if you block this processing the GUI will not update its status, in your case the problem is caused by time.sleep(), which is blocking, preventing the GUI from activating the state of displaying the window. So as a basic rule: do not use time.sleep() inside the main thread of a GUI, I suppose the time.sleep() emulates a task that takes a certain time, for that case you must execute this task from another thread and if you want update the GUI you must do it by means of signals, it should not be done directly.

In the following example I will use threading.Thread() to create a new thread and a signal to update the GUI:

import sys
import time
import threading
from PySide import QtCore, QtGui


class ProgressWindowWidget(QtGui.QWidget):
    progressSignal = QtCore.Signal(int)

    def __init__(self, parent=None):
        super(ProgressWindowWidget, self).__init__()
        self.init_ui()

    def init_ui(self):
        self.setGeometry(500, 500, 600, 100)
        self.setWindowTitle('Progress')

        self.layout_ = QtGui.QGridLayout()
        self.setLayout(self.layout_)

        self.progress_bar = QtGui.QProgressBar()
        self.progressSignal.connect(self.progress_bar.setValue)
        self.layout_.addWidget(self.progress_bar, 0, 0, 1, 1)

    def my_operations(self):
        print('do something 1')
        time.sleep(2)
        self.progressSignal.emit(33)
        print('do something 2')
        time.sleep(2)
        self.progressSignal.emit(66)
        print('do something 3')
        time.sleep(2)
        self.progressSignal.emit(100)


def main():
    app = QtGui.QApplication(sys.argv)
    progress_window = ProgressWindowWidget()
    progress_window.show()
    t = threading.Thread(target=progress_window.my_operations)
    t.start()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thank you! But I added the time.sleep in order to emulate the operations I'm actually trying to perform (such a copying files), and with these operations, the problem remains. What I'm trying to achieve is to load the ui and then, after it's loaded, to maybe trigger trigger an event that would perform `my_operations`. But I'm going to look into your solution :) – Munshine Sep 20 '18 at 18:13
  • @Munshine If you check my solution, point that out, so my solution should work with time.sleep() or with some heavy task like copying files, if my answer helps you do not forget to mark it as correct, if you do not know how to do it, review the [tour], That is the best way to thank. :-) – eyllanesc Sep 20 '18 at 18:21