2016-07-11 6 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?

+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

Я думаю, что это не так: Насколько я знаю, filedialog будет делать то же самое, что и все диалоги, когда вы вызываете " exec ", и начать свой собственный внутренний цикл событий, см. также здесь: http://stackoverflow.com/a/33606782/369009:« Это может быть источником неприятных ошибок: (Почти) все может произойти до того, как exec() вернется , внешние события (таймеры, сеть, IPC, что угодно) могут вызывать слоты, вызывать другие диалоги и т. д. J " –

 Смежные вопросы

  • Нет связанных вопросов^_^