2016-07-11 5 views
2

J'utilise actuellement QFileDialog::getOpenFileName. Cependant, comme suggéré dans this article, cela se bloque lorsque l'application principale se ferme alors que la boîte de dialogue est ouverte. Vous pouvez voir un exemple de la façon de reproduire le plantage ici:Exécutez QFileDialog :: getOpenFileName sans boucle d'événement distincte?

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

Je peux utiliser QFileDialog avec le constructeur normal au lieu, comme décrit here. Cependant, alors je ne semble pas obtenir le dialogue ouvert de fenêtres de fichier natif.

Existe-t-il un moyen d'obtenir un programme qui ne plante pas et d'utiliser la boîte de dialogue d'ouverture de fichier Windows native via Qt?

+0

Pourquoi la principale proche de l'application lorsque la boîte de dialogue est ouverte? Tu ne peux pas empêcher ça? – drescherjm

+0

Non, un thread distinct peut potentiellement générer une erreur. Dans ce cas, l'application est fermée et tous les widgets sont détruits. Cela fonctionne bien (tous les destructeurs appropriés sont appelés), à l'exception d'un getOpenFileName encore en cours d'exécution. –

+2

Avez-vous affecté un parent? - peut aussi poster votre code pour appeler le dialogue en cas il y a quelque chose d'évident –

Répondre

2

Si vous fermez votre main_window au lieu de le supprimer, vous n'obtiendrez aucun plantage. Au fait, vous pouvez vérifier s'il ya QFileDialog ouvert pour éviter une mauvaise sortie de l'application.

Dans l'exemple suivant, je ferme la boîte de dialogue, mais vous pouvez mettre en œuvre une autre solution:

#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

Merci, bonne idée! Bien que cela semble un peu hacky avec le casting ...;) –

+0

@ JanRüegg Eh bien, oui: D C'est juste un exemple: D Dans tous les cas, 'main_window-> close();' est la clé ici. – Tarod

0

La conception de votre application est cassée. L'arrêt de l'application se produit normalement lorsque la boucle d'événement le plus à l'extérieur du thread principal existe. Cela ne se produira pas si une boîte de dialogue de fichier est active - par définition, sa boucle d'événements est en cours d'exécution. Ainsi, vous faites quelque chose que vous ne devriez pas faire, et la boîte de dialogue du fichier est simplement un bouc émissaire, ou un canari dans la mine de charbon indiquant le brisement ailleurs.

+0

Je pense que ce n'est pas vrai: A ma connaissance, le classialog fera la même chose que tous les dialogues quand vous appelez " exec ", et lance sa propre boucle d'événement interne, voir aussi ici: http://stackoverflow.com/a/33606782/369009:" Cela peut être une source de bogues désagréables: (Presque) tout peut arriver avant que exec() ne retourne , les événements externes (minuteries, réseau, IPC, peu importe) peuvent appeler des logements, faire apparaître d'autres boîtes de dialogue, etc. J " –