2016-11-12 7 views
1

Предположим, у меня есть задача сбора файлов, а затем копирования. При сборе QProgressBar отображается некоторый неопределенный, «занятый» статус. После этого процесс переходит к копированию собранных файлов и показывает прогресс. Проблема в том, что я могу делать все это, но не вместе в непрерывном процессе. Вниз маленький код в PySide, который показывает, что это работает, нажимая QButton 1 и 2, но не в непрерывной задаче. Пожалуйста помоги.Как добиться перехода в QProgressBar из «занятого» типа в стандартный режим прогресса?

import sys, time 
from PySide.QtGui import * 
from PySide.QtCore import * 

class WidgetWithBar(QWidget): 
    def __init__(self): 
     super(WidgetWithBar, self).__init__() 

     self.progress = QProgressBar(self) 
     self.progress . setAlignment(Qt.AlignJustify) 
     self.progress . setValue(0) 

     button1   = QPushButton("Waiting for Job", self) 
     button1   . clicked.connect(self.wait) 
     button2   = QPushButton("Doing Job", self) 
     button2   . clicked.connect(self.go) 

     self.layout = QVBoxLayout() 
     self.layout.addWidget(self.progress) 
     self.layout.addWidget(button1) 
     self.layout.addWidget(button2) 
     self.setLayout(self.layout) 

    def wait(self): 
     self.progress.setRange(0,0) 
     # -- this two lines to comment out 
     #time.sleep(2) 
     #self.go() 
     # -- EOLines to comment out 

    def go(self): 
     n = 20 
     self.progress.setRange(0,n) 
     # DO SOMETHING TO SHOW THE PROGRESS 
     for t in range(n): 
      time.sleep(.1) 
      self.progress.setValue(t+1) 

def main(): 
    app = QApplication(sys.argv) 
    w = WidgetWithBar() 
    w.show() 
    sys.exit(app.exec_()) 

if __name__ == '__main__': 
    main() 

Так что, если я закомментировать две верхние строки, чтобы запустить обе функции нажатием только первой кнопки, индикатор не будет показывать «занято» режим на всех!

ответ

2

Вы должны выполнять трудоемкую работу в отдельном потоке и излучать сигналы для обновления прогресса. Ниже приведена простая демонстрация на основе вашего примера:

import sys, time, random 
from PySide.QtGui import * 
from PySide.QtCore import * 

class Worker(QThread): 
    progressChanged = Signal(int, int) 

    def run(self): 
     items = [] 
     count = random.randint(5, 10) 
     print('collecting items...') 
     while len(items) < count: 
      items.append(1) 
      time.sleep(.5) 
     print('processing items...') 
     for index, item in enumerate(items): 
      self.progressChanged.emit(index, count) 
      time.sleep(0.5) 

class WidgetWithBar(QWidget): 
    def __init__(self): 
     super(WidgetWithBar, self).__init__() 

     self.progress = QProgressBar(self) 
     self.progress . setAlignment(Qt.AlignJustify) 
     self.progress . setValue(0) 

     button1   = QPushButton("Start Job", self) 
     button1   . clicked.connect(self.handleStart) 

     self.layout = QVBoxLayout() 
     self.layout.addWidget(self.progress) 
     self.layout.addWidget(button1) 
     self.setLayout(self.layout) 

     self._worker = Worker(self) 
     self._worker.progressChanged.connect(self.handleProgress) 

    def handleProgress(self, step, count): 
     if not self.progress.maximum(): 
      self.progress.setRange(0, count - 1) 
     self.progress.setValue(step) 

    def handleStart(self): 
     if not self._worker.isRunning(): 
      self.progress.setRange(0,0) 
      self._worker.start() 

def main(): 
    app = QApplication(sys.argv) 
    w = WidgetWithBar() 
    w.show() 
    sys.exit(app.exec_()) 

if __name__ == '__main__': 
    main()