我需要在应用程序的测试中处理和关闭QFileDialog。 由:
调用的对话框QFileDialog::getOpenFileName( ... );
在测试中,我通过以下方式“捕获”此对话框:
QApplication::topLevelWidgets();
然后我通过QFileDialog API选择需要文件。
现在我应该关闭对话框以从QFileDialog :: getOpenFileName()获得有效的答案(文件名); 但是QDilaog的插槽没有效果(accept(),reject(),close()......)。对话框保持打开状态。
所描述的解决方案here有效,但在我的情况下不可行。我必须使用标准对话框。
有没有办法正确关闭它?
答案 0 :(得分:2)
QFileDialog :: getOpenFileName是一个静态方法,所以你受限于你可以用它做什么。
如果你想要更多控制,我建议创建一个QFileDialog实例并使用它。通过调用实例的close()函数,您可以以编程方式关闭对话框。
在回应这个不起作用的评论时,这里是示例代码: -
// Must create the FileDialog on the heap, so we can call close and the dialog is deleted
// Set the Qt::WA_DeleteOnClose flag if the instance is still required
QFileDialog* fileDlg = new QFileDialog(this, QString("Select Config file"), QDir::homePath(), QString("Config (*.xml)"));
// One shot timer to close the dialog programmatically
QTimer *timer = new QTimer(this);
timer->setSingleShot(true);
connect(timer, &QTimer::timeout, [=]()
{
fileDlg->close();
timer->deleteLater();
} );
timer->start(3000);
fileDlg->exec();
答案 1 :(得分:1)
要显示本机对话框,您必须运行exec()
或调用其中一个静态函数。
不幸的是,在Windows中,这会在Windows API中调用阻塞函数,使显示的对话框模态化,运行它自己的事件循环。如果不返回Qt事件循环,则无法使用信号/插槽接口执行close()
功能。
我试图通过直接从另一个线程调用close()
函数来绕过这个,但这会导致Qt尝试将事件发送到底层对话框。由于在Qt中不允许跨线程边界发送(而不是发布)事件,因此会生成致命错误。
所以,至少在Windows上看来,这是不可能的。
我没有在Windows以外的平台上测试过。我使用的代码是:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QFileDialog* fileDlg = new QFileDialog(0, QString("Select Config file"), QDir::homePath(), QString("Config (*.xml)"));
// spawn a new thread
QtConcurrent::run([=](){
QTimer timer;
timer.setSingleShot(true);
QEventLoop *loop = new QEventLoop;
QObject::connect(&timer, &QTimer::timeout, [=](){
fileDlg->close();
fileDlg->deleteLater();
loop->quit();
});
timer.start(3000);
loop->exec();
delete loop;
});
fileDlg->exec();
return a.exec();
}
答案 2 :(得分:0)
在Windows中,您可以使用WinAPI关闭对话框:
#define WAIT(A) while (!(A)) {}
HWND dialogHandle, button;
WAIT(dialogHandle = FindWindow(NULL, L"Open")); //write here title of the dialog
WAIT(button = FindWindowEx(dialogHandle, NULL, L"Button", L"&Open")); //write here title of the button to click
SendMessage(button, BM_CLICK, 0, 0);