我正在开发一个用户可以解析一些二进制文件的应用程序。一旦他点击"解析" - 按钮,他首先可以选择一些文件,然后解析。当应用程序正在处理文件时,我想显示一个模态对话框,通知用户有关进度(QProgressBar栏)和已解析的文件(QListView list / listModel)。
我目前的做法是覆盖QDialog-sublcass的exec()方法。这样我就可以打电话了
parseAssistant.exec()
目前的实现如下:
class ParseAssistant : public QDialog { public: int exec(); };
int ParseAssistant::exec()
{
bar->setMaximum(files.size());
this->show();
this->setModal(true);
for (int i = 0; i < files.size(); i++) {
PluginTable* table = parser.parse(files[i]);
// do something with the table
// saveTableintoDB();
// update GUI
// bar->setValue(i);
// listModel->insertRow(0, new QStandardItem(files[i]));
}
this->hide();
return QDialog::Accepted;
}
此(阻塞)方法运行后,用户已解析所有文件或取消了某处的进度。为了达到这个目的,我尝试在while循环中使用QApplication :: processEvents(由于它只在文件完成解析时才进展)或将重度计算外包给某些QConcurrent实现( :: run,:: mapped)。不幸的是,一旦QFuture完成,我不知道如何将程序流程返回到exec()方法,而不依赖于一些CPU密集的循环,如:
while (!future.isFinished()) { QApplication::processEvents(); }
是否有一种更智能的方法来建立模态对话框,该对话框运行繁重的计算(可能被用户取消)而不会阻止事件循环?
答案 0 :(得分:2)
我首先不会将Qdialog
作为子类,但只需使用QFutureWatcher
并将观察者finished
信号连接到对话框close
,这样:
QDialog d;
QFutureWatcher<void> watcher;
QObject::connect(&watcher, &QFutureWatcher<void>::finished, &d, &QDialog::close);
QFuture<void> future = QtConcurrent::run(your_parse_function);
watcher.setFuture(future);
d.exec();
//control returns here when your_parse_function exits
parse函数可以是QObject派生类中的方法,如下所示:
class Parser : public QObject
{
Q_OBJECT
public:
void parse()
{
for (int i = 0; i < files.size(); i++) {
PluginTable* table = parser.parse(files[i]);
emit fileParsed(i, files.size);
// ...
}
}
signals:
void fileParsed(int id, int count);
};
您可以将fileParsed
信号连接到所选的插槽,然后相应地设置进度条值。
答案 1 :(得分:0)
我个人的做法是:
Qt::QueuedConnection
)