简体   繁体   English

如何以编程方式关闭QFileDialog?

[英]How to close QFileDialog programmatically?

I need to process and close QFileDialog in tests of the application. 我需要在应用程序的测试中处理并关闭QFileDialog。 The dialog invoked by: 该对话框由以下人员调用:

QFileDialog::getOpenFileName( ... );

In the test I 'catch' this dialog by: 在测试中,我通过以下方式“捕获”此对话框:

QApplication::topLevelWidgets();

Then I choose need file by QFileDialog API. 然后我通过QFileDialog API选择需要的文件。

And now I should close the dialog to get valid answer (filename) from QFileDialog::getOpenFileName(); 现在,我应该关闭对话框以从QFileDialog :: getOpenFileName();获得有效答案(文件名); But QDilaog's slots has no effect (accept(), reject(), close()... ). 但是QDilaog的插槽没有作用(accept(),reject(),close()...)。 The dialog stays opened. 对话框保持打开状态。

The solution described here works, but it is no option in my case. 这里描述的解决方案是可行的,但是在我看来,这是没有选择的。 I must to use standard dialogs. 我必须使用标准对话框。

Is there a way to close it properly? 有没有办法正确关闭它?

QFileDialog::getOpenFileName is a static method, so you're limited by what you can do with it. QFileDialog :: getOpenFileName是一个静态方法,因此您会受到限制。

If you want more control, I suggest creating an instance of QFileDialog and using that instead. 如果您想获得更多控制权,建议您创建一个QFileDialog实例并使用它。 By calling the instance's close() function, you can programmatically close the dialog. 通过调用实例的close()函数,可以以编程方式关闭对话框。

In response to the comment that this doesn't work, here's example code:- 为了回应这种说法不起作用,下面是示例代码:-

// 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();

In order for to display a native dialog, you have to run exec() or call one of the static functions. 为了显示本机对话框,您必须运行exec()或调用静态函数之一。

Unfortunately, in Windows, this calls a blocking function in the Windows API making the displayed dialog modal, running it's own event loop. 不幸的是,在Windows中,这会调用Windows API中的阻塞函数,使显示的对话框具有模式,并运行其自己的事件循环。 Without returning to the Qt event loop, you cannot execute the close() function using the signals/slots interface. 如果不返回Qt事件循环,则无法使用信号/插槽接口执行close()函数。

I tried to bypass this by calling the close() function directly from another thread, but this results in Qt trying to send an event to the underlying dialog. 我试图通过直接从另一个线程调用close()函数来绕过此操作,但这导致Qt尝试将事件发送到基础对话框。 Since sending (as opposed to posting) events across thread boundaries is not allowed in Qt, a fatal error is generated. 由于在Qt中不允许跨线程边界发送(相对于发布)事件,因此会产生致命错误。

So, it seems for Windows at least, this is not possible. 因此,看来至少对于Windows,这是不可能的。

I have not tested on platforms other than Windows. 我没有在Windows以外的平台上进行测试。 The code I used was: 我使用的代码是:

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();
}

In Windows you can use WinAPI to close the dialog: 在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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM