2015-05-10 3 views
2

Я хотел бы показать ход вычисления, если в моем графическом интерфейсе. Для этого я хотел бы обновлять свой лейбл PyQt4 каждый раз при расчете. Я знаю, что я должен использовать поток, но это не сработает. Ничего не меняется, и после завершения цикла метка обновляется до «100%». Несмотря на то, что поток работает, значение все равно не будет плавно обновляться. В моем коде есть комментарии, объясняющие, что к чему. Пожалуйста, помогите мне :)Обновление PyQt4 GUI во время цикла

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, вот мое решение, но с памятью проблемы протечки

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 
+0

Если вы хотите узнать, почему ваш обновленный код утечки памяти, я предлагаю вам расспросить об этом в новом вопросе. Тем не менее, я настоятельно рекомендую вам вернуться к потокам и реализовать ответ, который я предоставил. Темы предназначены для долгого кода в них, оставляя графический интерфейс реагирующим в основном потоке. Использование 'processEvents()' на самом деле просто взломать, чтобы ваш графический интерфейс реагировал. –

+0

Да, вот что я собираюсь делать. Вы на самом деле дали мне некоторое представление о том, как это должно быть сделано и почему. Спасибо за это :) – Zwierzak

ответ

1

thread.run() Calling в том, что вы не делаете то, что вы думаете. В настоящее время он просто выполняет метод thread.run() в основном потоке.

Это вызов thread.start(), который запускает поток и автоматически вызывает метод thread.run(). Таким образом, вам нужен цикл while внутри метод thread.run().

Это связано с тем, что вы хотите передать полный контроль над потоком и закончить метод euler, чтобы управление можно было возвращать в цикл событий GUI (чтобы он мог обрабатывать перерисовки и метод обновления индикатора выполнения) как можно быстрее. Вы не должны пытаться управлять выполнением потоков из основного потока.

+0

Я решил эту проблему, обновив свой элемент управления, а затем используя processEvents() внутри цикла while, но когда этот цикл достаточно длинный (например, 1000000 раз), я получаю утечку памяти - мои программы начинают есть огромное количество оперативной памяти. Любая идея почему? : P – Zwierzak

+0

@Zwierzak Не обойдя свой новый код, нет. Но по-прежнему звучит так, будто вы используете потоки неправильно. Вы поняли, что я написал? –

+0

Да, я получил это, но включение этого цикла в цикл выполнения метода Thread выглядит плохой идеей, потому что этот цикл иногда работает примерно за 1 минуту до завершения задачи. Я думаю, это плохая идея, чтобы такой длинный цикл был нитью. У меня есть обновления моего сообщения с моим решением, которое я сделал до сих пор. – Zwierzak