簡體   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