繁体   English   中英

如何以编程方式关闭QFileDialog?

[英]How to close QFileDialog programmatically?

我需要在应用程序的测试中处理并关闭QFileDialog。 该对话框由以下人员调用:

QFileDialog::getOpenFileName( ... );

在测试中,我通过以下方式“捕获”此对话框:

QApplication::topLevelWidgets();

然后我通过QFileDialog API选择需要的文件。

现在,我应该关闭对话框以从QFileDialog :: getOpenFileName();获得有效答案(文件名); 但是QDilaog的插槽没有作用(accept(),reject(),close()...)。 对话框保持打开状态。

这里描述的解决方案是可行的,但是在我看来,这是没有选择的。 我必须使用标准对话框。

有没有办法正确关闭它?

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

为了显示本机对话框,您必须运行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();
}

在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