QProgressBar не показывает прогресс? - PullRequest
9 голосов
/ 11 мая 2010

Моей первой наивностью при обновлении моего индикатора выполнения было включение следующих строк в мой цикл, который выполняет обработку, делая что-то вроде этого:

while(data.hasMoreItems())
{
    doSomeProcessing(data.nextItem())

    //Added these lines but they don't do anything
    ui->progressBar->setValue(numberProcessed++);
    ui->progressBar->repaint();
}

Я думал, что добавление repaint() сделает приостановку выполнения, пока обновляется графический интерфейс, но, видимо, не все так просто. Посмотрев на вопросы:

Ошибка QProgressBar
Индикатор выполнения не показывает прогресс

Похоже, мне придется поместить обработку данных в другой поток, а затем подключить сигнал из потока обработки данных к потоку GUI для обновления индикатора выполнения. Я довольно неопытен с GUI и потоками, и мне было интересно, может ли кто-нибудь просто указать мне правильное направление, то есть какие классы Qt я должен использовать для этого. Я предполагаю, что мне нужен объект QThread, но я просматривал документацию QProgressBar, но он не поднимает тему потоков.

Ответы [ 3 ]

11 голосов
/ 11 мая 2010

Как отметили @rjh и @Georg, есть два разных варианта:

  1. Принудительная обработка событий с использованием QApplication :: processEvents () , ИЛИ
  2. Создать поток , который испускает сигналы, которые можно использовать для обновления индикатора выполнения

Если вы выполняете какую-либо нетривиальную обработку, я бы рекомендовал перенести обработку в поток.

Самое важное, что нужно знать о потоках, это то, что кроме основного потока GUI (который вы не запускаете и не создаете), вы никогда не сможете обновить графический интерфейс непосредственно из потока .

Последний параметр QObject :: connect () - это перечисление Qt :: ConnectionType , которое по умолчанию учитывает, участвуют ли потоки.

Таким образом, вы должны иметь возможность создать простой подкласс QThread, который выполняет обработку:

class DataProcessingThread : public QThread
 {

 public:
     void run();
 signals:
     void percentageComplete(int);
 };

 void MyThread::run()
 {
    while(data.hasMoreItems())
    {
      doSomeProcessing(data.nextItem())
      emit percentageCompleted(computePercentageCompleted());
    }
 }

А потом где-нибудь в вашем коде GUI:

DataProcessingThread dataProcessor(/*data*/);
connect(dataProcessor, SIGNAL(percentageCompleted(int)), progressBar, SLOT(setValue(int));
dataProcessor.start();
3 голосов
/ 11 мая 2010

Вам необходимо периодически вызывать QApplication::processEvents() внутри цикла обработки, чтобы он мог обрабатывать события пользовательского интерфейса.

Как говорит Георг, Qt представляет собой однопоточную кооперативную многозадачную среду. Вы получаете полный контроль над своим процессом, пока не добровольно откажетесь от него с помощью processEvents () - пока вы не сделаете это, Qt не сможет обновлять элементы пользовательского интерфейса, обрабатывать асинхронные HTTP-запросы, обрабатывать ввод или почти все остальное. Это зависит от вас, чтобы убедиться, что материал получает временной интервал, пока вы находитесь в длинном цикле обработки.

2 голосов
/ 11 мая 2010

Вы можете создать подкласс QThread, который излучает сигнал progressChanged, который вы подключаете к QProgressBar.

connect() устанавливает соединения auto connections по умолчанию. Это означает, что механизм сигнальных слотов уже позаботился о проблемах с потоками, поэтому вам не нужно об этом беспокоиться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...