在 QDialog::exec() 期间使用 QThreads 执行 QWidget::grab()

Using QThreads to execute QWidget::grab() during QDialog::exec()

我编写了一个 Qt 程序,当用户上传某个数据文件并点击一个按钮时,会生成一系列图表。当按下按钮时,程序将计算一系列计算并绘制一些图形,并在函数调用 QDialog::exec() 的屏幕上显示它们。我想要实现的是 grab 使用 QWidget::grab() 生成的图的屏幕截图。所以基本上 QWidget::grab()QDialog::exec() 之后被调用。但是由于 QDialog::exec() 保持 运行 直到特定的 window 被用户关闭,所以在关闭 window 之后调用 QWidget::grab() 不会产生预期的结果。

这是我的代码的一部分;

mainwindow.cpp

    graphWindow.setWindowState(Qt::WindowMaximized);
    graphWindow.exec(); 
    graphWindow.savePlots();

graphWindow.savePlots()

void GraphWindow::savePlots()
{ 

  QStringList plotNames;
  plotNames << "Income Statement (Plot A)" << "Income Statement (Plot B)" << "Balance Sheet (Plot A)"
            << "Balance Sheet (Plot B)" << "Cash Flow Plot" << "Holistic Stock Performance";

  for(int item = 0; item < ui->graphTab->count(); item++)
  {
      ui->graphTab->setCurrentIndex(item);
      QWidget * currentWidget = ui->graphTab->widget(item);

      int height = currentWidget->height();
      int width = currentWidget->width();
      int x = currentWidget->x();
      int y = currentWidget->y();

      QRect grabRect(x,y,width,height);

      //destImagePath is a global variable
      QString imageFilePath = destImagePath;
      imageFilePath.append(plotNames.at(item));
      imageFilePath.append(".png");

      currentWidget->grab(grabRect).save(imageFilePath);
  }

     //Reset to first tab after grab
     ui->graphTab->setCurrentIndex(0);
 }

我正在考虑通过 运行 另一个 QThread 绕过 QDialog::exec(),它执行 GraphWindow::savePlots() 而 window 仍然是 运行 所以该屏幕抓取会产生所需的结果。

有没有更好的方法来做到这一点?我认为创建一个新的 QThread 只是为了调用一个函数是非常低效的。即使不是,您能否解释一下如何在并发 QThreads.

中实现

在您的情况下,实际上没有必要使用 QThread 或使用 QtConcurrent::run,您可以改为使用

将对主线程上的槽的调用排队
QTimer::singleShot(0, &graphWindow, &GraphWindow::savePlots);
graphWindow.exec();

在你的情况下,它的优点是它将 运行 在主线程上,所以你不必为捕获而操心线程、同步和所有类似的事情(即使 Qt 使更容易)。

此方法的唯一限制是在捕获期间将有效地"freeze"您的应用程序。考虑到它明显少于一秒,这通常应该是完全可以接受的。