QProgressDialog 不立即显示

QProgressDialog does not display immediately

我有一个 QProgressDialog 想要立即显示

QProgressDialog *progress = new QProgressDialog("Downloading files...", 
  "Cancel", 0, 2*selection.size()+1);
progress->setMinimumDuration(0);
progress->setWindowModality(Qt::WindowModal);
progress->setValue(0);

然后我运行一个for循环任务,最后分配最大值:

for (int i = 1; i < selection.size()+1; ++i) 
{
  progress->setValue(2*i-1);
  if (progress->wasCanceled())
    break;
  do_half_task();
  progress->setValue(2*i);
  if (progress->wasCanceled())
    break;
  do_second_half();
}
progress->setValue(2*selection.size()+1);

但是使用这段代码,对话框 window 边框出现,内部没有任何小部件是透明的,并且只有在完整的 for 循环完成时才会填充标签和进度条。

我认为这是因为只有在完整循环完成后,Qt 才能计算每个步骤的持续时间,并检查它是否为 >0,我将其设置为最短持续时间。但是,从文档中我看到

minimumDuration : int

If set to 0, the dialog is always shown as soon as any progress is set. The default is 4000 milliseconds.

在设置 progress->setValue(1) 后,我希望对话框会在第一次循环中立即出现。

如何让我的 QProgressDialog 立即显示?

不确定这是否也适用于 Qt 但是在 C# 中,如果你 运行 在同一个线程中执行你的代码,比如

ProcessBar p = new ProcessBar();
this.Controls.Add(p);
...
for (int i = 0; i < 100; i++) {
  p.Value = i;
  Thread.Sleep(1);
}

那么你的问题是你的表单没有到达重绘的代码。

也许尝试在另一个线程中执行循环?

当您让主线程进入循环时,它无法进行任何事件处理,直到循环结束并且您的方法 returns.

因此它只能在您完成后处理所有 "paint update" 个请求。

您可以在循环内部调用 QCoreApplication::processEvents() 以允许它 return 进行一段时间的事件处理。

要立即显示对话框,只需调用 QProgressDialog::show()