在 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"您的应用程序。考虑到它明显少于一秒,这通常应该是完全可以接受的。
我编写了一个 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"您的应用程序。考虑到它明显少于一秒,这通常应该是完全可以接受的。