Issue
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
Solution
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()
Answered By - eyllanesc
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.