【问题标题】:Run QFileDialog::getOpenFileName without separate event loop?在没有单独的事件循环的情况下运行 QFileDialog::getOpenFileName?
【发布时间】:2016-07-11 13:01:46
【问题描述】:

我现在正在使用QFileDialog::getOpenFileName。但是,正如this article 中所建议的那样,当主应用程序在对话框打开时关闭时会崩溃。您可以在此处查看如何重现崩溃的示例:

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 文件打开对话框?

【问题讨论】:

  • 对话框打开时为什么主应用程序关闭?你不能阻止吗?
  • 不,有一个单独的线程正在运行,可能会引发错误。在这种情况下,应用程序将关闭并且所有小部件都将被销毁。这工作正常(所有适当的析构函数等都被调用),除了仍在运行的 getOpenFileName。
  • 你分配了父母吗? - 也可以发布你的代码来调用对话框,以防有任何明显的情况

标签: c++ qt qt5 fileopendialog qeventloop


【解决方案1】:

如果您关闭 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;
}

【讨论】:

  • 谢谢,好主意!虽然它的选角看起来确实有点 hacky... ;)
  • @JanRüegg 嗯,是的 :D 这只是一个例子 :D 无论如何,main_window-&gt;close(); 是这里的关键。
【解决方案2】:

您的应用程序设计已损坏。应用程序的关闭通常发生在主线程中最外层的事件循环存在时。当文件对话框处于活动状态时,这不会发生 - 根据定义,它的事件循环正在运行。因此,您正在做您不应该做的事情,而文件对话框只是替罪羊,或者是煤矿中的金丝雀,表明其他地方已经破碎。

【讨论】:

  • 我认为那不是真的:据我所知,当您调用“exec”时,文件对话框将与所有对话框执行相同的操作,并启动其自己的内部事件循环,另请参见此处:stackoverflow.com/a/33606782/369009: “这可能是令人讨厌的错误的来源:(几乎)任何事情都可能在 exec() 返回之前发生,外部事件(计时器、网络、IPC 等)可以调用插槽、导致其他对话框出现等。J”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-12
  • 1970-01-01
  • 2015-11-04
  • 1970-01-01
  • 1970-01-01
  • 2022-08-19
  • 1970-01-01
相关资源
最近更新 更多