Мое первое наивное при обновлении моего индикатора выполнения должно было включать следующие строки в мой цикл, который делает обработку, делая что-то вроде этого:
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, но она не поднимает тему поточной обработки.
Как отметили @rjh и @Georg, есть по сути два варианта:
Если вы делаете любую нетривиальную обработку, я бы рекомендовал перенести обработку в поток.
Самое важное, что нужно знать о потоках, это то, что за исключением основного потока 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();
Вы можете создать подкласс QThread
, который испускает сигнал progressChanged
, который вы подключаете к QProgressBar
.
connect()
делает соединения автоматическими
по умолчанию. Это означает, что механизм signal-slot-mechanism уже позаботился о потоковых соединениях за вас, поэтому вам не нужно беспокоиться об этом.
Вам необходимо периодически вызывать QApplication :: processEvents ()
внутри вашего цикла обработки, чтобы он мог обрабатывать события пользовательского интерфейса.
Как говорит Георг, Qt - это однопоточная кооперативная многозадачная среда. Вы получаете полный контроль над своим процессом, пока не откажетесь от него добровольно с помощью processEvents () - пока вы этого не сделаете, Qt не сможет обновлять элементы пользовательского интерфейса, обрабатывать асинхронные HTTP-запросы, обрабатывать ввод или что-то еще. Вам решать, чтобы материал был сокращен, пока вы находитесь в длинном цикле обработки.