Reputation: 686
I would like to show progress of calculation if in my GUI. To do so I would like to update my PyQt4 label each time a calculation is made. I know that I am supposed to use thread to do it, but it doesn't work. Nothing changes, and after while loop is complete, the label is updated to "100%".Even though the thread is working the value still won't update smoothly. There are comments in my code explaining what is what. Please help me :)
from PyQt4 import QtGui, QtCore
import time
class MyThread(QtCore.QThread):
trigger = QtCore.pyqtSignal(int)
def __init__(self, progress, parent=None):
super(MyThread, self).__init__(parent)
self.progress = progress #progress is a PyQt4 label object
def update_progress(self, value):
self.progress.setText(QtGui.QApplication.translate("Dialog", "Progress: %s " % value, None))
print "I was called", value
print self.progress #prints <PyQt4.QtGui.QLabel object at 0x0000000008151708>
#as you can see the object is passed all right
def run(self, value):
self.trigger.emit(value)
class Calculus:
def __init__(self):
print "object created"
@staticmethod
def euler(b,h,progress):
#progress is a PyQt4 label object, b and h are some integers
actions_done = 0
actions_number = b / h
thread = MyThread(progress)#create a thread
thread.trigger.connect(thread.update_progress)#connect it with a update function
thread.start()#start the thread
while t <= b:
actions_done+=1
progress_value = (actions_done/actions_number)*100
thread.run(progress_value)#emit signal?
t += h
thread.terminate()
@EDIT, here is my solution but with memory leaking problem
from PyQt4 import QtGui
class Calculus:
def __init__(self):
print "object created"
@staticmethod
def update_progress(self,value,ui_object):
ui_object.setText(QtGui.QApplication.translate("Dialog", "Progress: %s %%" % value, None))
#MEMORY LEAK WHEN UPDATING TOO MUCH (H=0.0001 AND B=1000)
QtGui.QApplication.processEvents() #update gui for pyqt
@staticmethod
def euler(b,h,progress):
actions_done = 0
actions_number = b * (1./h) #t = t+h. When h = 0.01 we need to perform t=t+h 100(1/h) times to get 1.
#when t varies from 0 to b, then we need to multiply this 1 * b(end time)
#so we get b * (1/h) as a number of actions to perform
scale = actions_number * 0.01
while t <= b:
actions_done+=1
progress_value = (actions_done/actions_number)*100
if (actions_done % scale == 0):
Calculus.update_progress(None,progress_value, progress)
t += h
Upvotes: 2
Views: 1482
Reputation: 11849
Calling thread.run()
in the way that you are does not do what you think it does. Currently it is simply executing the thread.run()
method in the main thread.
It is the call to thread.start()
which starts the thread, and automatically calls the thread.run()
method. As such, you need the while loop inside the thread.run()
method.
This is because you want to pass complete control over to the thread, and finish the euler
method so that control can be returned to the GUI event loop (so it can process redraws, and the method to update the progress bar) as soon as possible. You should not be trying to manage the threads execution from the main thread.
Upvotes: 1