我在更新进度条时的第一个天真就是在我的循环中包含以下几行,正在进行处理,制作如下:
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 Error
Progress bar is not showing progress
看起来我将不得不将数据处理放在不同的线程中,然后将来自数据处理线程的信号连接到GUI线程以更新进度条。我对GUI和线程缺乏经验,我想知道是否有人能指出我正确的方向,即我应该使用什么Qt类来实现。我猜我需要一个QThread对象,但我一直在查看QProgressBar文档,但它没有提出线程主题。
答案 0 :(得分:11)
正如@rjh和@Georg指出的那样,基本上有两种不同的选择:
如果您正在进行任何非平凡的处理,我建议将处理移至线程。
关于线程最重要的事情是除了主GUI线程(你没有开始也没有创建),你永远不能直接从线程中更新GUI 。< / p>
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();
答案 1 :(得分:3)
您需要在处理循环内定期调用QApplication::processEvents()
以让它处理UI事件。
正如乔治所说,Qt是一个单线程的合作多任务环境。您可以完全控制您的进程,直到您使用processEvents()自愿放弃它 - 直到您这样做,Qt无法更新UI元素,处理异步HTTP请求,处理输入或其他任何事情。当你处于漫长的处理循环中时,你应该确保这些东西能够获得时间片。
答案 2 :(得分:2)
您可以创建一个发出信号QThread
的{{1}}子类,并将其连接到progressChanged
。
QProgressBar
会建立连接connect()
。这意味着信号槽机制已经为您解决了线程问题,因此您无需担心这一点。