2016-07-11 70 views
2

我現在使用QFileDialog::getOpenFileName。但是,如this article中所建議的那樣,當對話框打開時主應用程序關閉時會崩潰。你可以看到如何在這裏重現崩潰的例子:運行QFileDialog :: getOpenFileName沒有單獨的事件循環?

int main(int argc, char **argv) { 
    QApplication application{argc, argv}; 

    QMainWindow *main_window = new QMainWindow(); 
    main_window->show(); 

    QPushButton *button = new QPushButton("Press me"); 
    main_window->setCentralWidget(button); 

    QObject::connect(button, &QPushButton::clicked, [main_window]() { 
    QTimer::singleShot(2000, [main_window]() { delete main_window; }); 

    QFileDialog::getOpenFileName(main_window, "Close me fast or I will crash!"); 
    }); 

    application.exec(); 
    return 0; 
} 

我可以使用QFileDialog與正常的構造函數代替,如所描述here。但是,我似乎並沒有得到本地Windows文件打開對話框。

有沒有辦法讓一個非崩潰的程序,並通過Qt使用本地Windows文件打開對話框?

+0

爲什麼主應用程序關閉時,對話框打開?你不能阻止嗎? – drescherjm

+0

不,有一個單獨的線程正在運行,可能會引發錯誤。在這種情況下,應用程序被關閉並且所有小部件都被銷燬。這工作正常(所有適當的析構函數等都被調用),除了仍在運行的getOpenFileName。 –

+2

你有分配給家長嗎? - 不妨發佈你的代碼來調用對話框,以防萬一有什麼明顯的變化 –

回答

2

如果關閉main_window而不是刪除它,則不會發生任何故障。

順便說一句,你可以檢查是否有任何QFileDialog打開,以避免錯誤的應用程序退出。

在下面的例子中,我關閉對話框,但你可以實現另一種解決方案:

#include <QTimer> 
#include <QApplication> 
#include <QMainWindow> 
#include <QPushButton> 
#include <QFileDialog> 
#include <QDebug> 

int main(int argc, char **argv) { 
    QApplication application{argc, argv}; 

    QMainWindow *main_window = new QMainWindow(); 
    main_window->show(); 

    QPushButton *button = new QPushButton("Press me"); 
    main_window->setCentralWidget(button); 

    QObject::connect(button, &QPushButton::clicked, [main_window]() { 
    QTimer::singleShot(2000, [main_window]() { 

     QObjectList list = main_window->children(); 

     while (!list.isEmpty()) 
     { 
      QObject *object= list.takeFirst(); 

      if (qobject_cast<QFileDialog*>(object)) 
      { 
       qDebug() << object->objectName(); 
       QFileDialog* fileDialog = qobject_cast<QFileDialog*>(object); 
       fileDialog->close(); 
      } 
     } 

     main_window->close(); 
    }); 

    QFileDialog::getOpenFileName(main_window, "Close me fast or I will crash!"); 
    }); 

    application.exec(); 
    return 0; 
} 
+0

謝謝,好主意!雖然它看起來有點冒險...;) –

+0

@JanRüegg嗯,是的:D這只是一個例子:D無論如何,'main_window-> close();'是這裏的關鍵。 – Tarod

0

您的應用程序的設計已損壞。當主線程中的最後一個事件循環存在時,通常會關閉應用程序。這在文件對話框處於活動狀態時不會發生 - 根據定義,其事件循環正在運行。因此,你正在做一些你不應該做的事情,文件對話只是一個替罪羊,或者是煤礦裏的一個金絲雀,指示其他地方的破碎。

+0

我認爲那不是真的:據我所知,當你打電話給「對話框」的時候, exec「,並啓動自己的內部事件循環,另請參見:http://stackoverflow.com/a/33606782/369009:」這可能是一個令人討厭的bug的來源:(幾乎)任何事情都可能發生在exec()返回之前,外部事件(定時器,網絡,IPC等)可以調用插槽,導致其他對話框出現,等等。「J」 –

相關問題