Reputation: 1502
This is my code. Iam trying to show a progress bar that shows the loading status till all the widgets are properly loaded but the progress bar wont update properly.It only updates in the end of the process and shows 100%
from PySide.QtGui import *
from PySide.QtCore import *
import time
import sys
class Mainwindow(QWidget):
def __init__(self):
QWidget.__init__(self)
self.progress = QProgressBar()
self.progress.setRange(0, 100)
self.worker = Worker()
self.thread = QThread()
self.worker.moveToThread(self.thread)
self.worker.relay.connect(self.update_progress)
self.thread.start()
self.progress.show()
self.add_tabs()
def add_tabs(self):
for i in xrange(10000):
i*i
time.sleep(1)
self.worker.process()
for i in xrange(10000):
i*i
time.sleep(1)
self.worker.process()
for i in xrange(10000):
i*i
time.sleep(1)
self.worker.process()
for i in xrange(10000):
i*i
time.sleep(1)
self.worker.process()
for i in xrange(10000):
i*i
time.sleep(1)
self.worker.process()
for i in xrange(10000):
i*i
time.sleep(1)
self.worker.process()
for i in xrange(10000):
i*i
time.sleep(1)
self.worker.process()
for i in xrange(10000):
i*i
time.sleep(1)
self.worker.process()
for i in xrange(10000):
i*i
time.sleep(1)
self.worker.process()
for i in xrange(10000):
i*i
time.sleep(1)
self.worker.process()
@Slot(int)
def update_progress(self, x):
self.progress.setValue(x * 10)
class Worker(QObject):
relay = Signal(int)
def __init__(self, parent=None):
super(Worker, self).__init__(parent)
self.x = 0
def process(self):
while self.x < 10:
self.x = self.x+1
self.relay.emit(self.x)
print self.x
return True
if __name__=='__main__':
app=QApplication(sys.argv)
win=Mainwindow()
win.show()
app.exec_()
sys.exit(0)
Edit 1 It is claimed that my question is a duplicate of how to make QtextEdit can update data realtime and no stuck UI but i have tried process events, process events are for loops or the process we do in the front end. In my case those loops you see with xrange are backend processes in my real program. The xrange loops were used here to have an understanding, that i have real backend tasks running for which i cannot use process events. Sorry for not making myself clear in the first place. I need a Qthread based solution.
Upvotes: 2
Views: 4195
Reputation: 6075
If I understood correctly, you want to do some heavy processing on a separate thread and update the progress on the main GUI. So all the processing done in MainWindow.add_tabs
should actually be done in the worker.
Also, it seems like you want to use QProgressDialog
(pop-up window) instead of QProgressBar
.
Here's a solution, with a responsive GUI:
from PySide.QtGui import *
from PySide.QtCore import *
import time
import sys
class Mainwindow(QWidget):
def __init__(self):
QWidget.__init__(self)
self.worker = Worker()
self.thread = QThread()
self.worker.moveToThread(self.thread)
self.worker.workRequested.connect(self.thread.start)
self.thread.started.connect(self.worker.add_tabs)
self.worker.finished.connect(self.on_finish)
self.button=QPushButton("Add tabs")
self.button.clicked.connect(self.on_button_click)
self.button_responsive=QPushButton("Still responsive?")
self.button_responsive.clicked.connect(self.responsive)
self.progress = QProgressDialog("Progress","cancel",0,10)
self.progress.setCancelButton(None)
self.worker.relay.connect(self.update_progress)
vbox=QVBoxLayout()
vbox.addWidget(self.button)
vbox.addWidget(self.button_responsive)
self.setLayout(vbox)
def on_button_click(self):
self.button.setEnabled(False)
self.worker.request_work()
self.progress.setValue(0)
def on_finish(self):
self.button.setEnabled(True)
self.thread.quit()
def update_progress(self,value):
self.progress.setValue(value)
def responsive(self):
print("Yes!")
class Worker(QObject):
workRequested=Signal()
finished=Signal()
relay=Signal(int)
def __init__(self, parent=None):
super(Worker, self).__init__(parent)
self.x = 0
def request_work(self):
self.workRequested.emit()
def add_tabs(self):
self.x=0
for i in range(10):
#Do any processing
for i in xrange(10000):
i*i
time.sleep(1)
self.x+=1
self.relay.emit(self.x)
self.finished.emit()
if __name__=='__main__':
app=QApplication(sys.argv)
win=Mainwindow()
win.show()
sys.exit(app.exec_())
Upvotes: 3