Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PySide/PyQt: Execute functions after GUI loads

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

like image 820
Munshine Avatar asked Dec 05 '25 07:12

Munshine


1 Answers

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()
like image 67
eyllanesc Avatar answered Dec 07 '25 21:12

eyllanesc



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!