QProgressBar, не показывающий прогресс?

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

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

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

Я думал, добавляя repaint() сделал бы паузу выполнения, в то время как она обновила GUI, но по-видимому дело не в этом простой. После рассмотрения вопросов:

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

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

10
задан Community 23 May 2017 в 12:31
поделиться

3 ответа

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

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

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

Самое важное, что нужно знать о потоках, это то, что за исключением основного потока GUI (который вы не запускаете и не создаете), вы никогда не сможете обновить 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();
13
ответ дан 3 December 2019 в 20:40
поделиться

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

connect() делает соединения автоматическими по умолчанию. Это означает, что механизм signal-slot-mechanism уже позаботился о потоковых соединениях за вас, поэтому вам не нужно беспокоиться об этом.

2
ответ дан 3 December 2019 в 20:40
поделиться

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

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

3
ответ дан 3 December 2019 в 20:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: