QDialog закрывается сам по себе, как я могу это исправить?

Мои имена классов похожи на (что он делает) _ (тип), например: reg_QDialog

Вот код исполняемого dlg и, если принято, создание QMainWindow:

if(log_dlg->exec() == QDialog::Accepted)
{
    find_wnd = new find_QMainWindow();
    find_wnd->show();
}

log_dlg имеет 2 кнопки: «Enter» (вот результат принятия) и «Reg» (открывает новый dlg)

Код "Enter" и "Reg" находится здесь:

void log_QDialog::on_btn_enter_clicked()
{
    this->accept();
}

void log_QDialog::on_btn_reg_clicked()
{
    reg_QDialog *reg_dlg = new reg_QDialog();

    this->hide();
    if(reg_wnd->exec() == QDialog::Accepted)
    {
        //code
    }
    this->show();
}

Итак, вот проблема:

Step by step:
1) run the prog    //it starts with dlg_log 
2) "Reg"           //creating dlg_reg 
3) accept dlg_reg  //returning to dlg_log 
4) "Enter"         //trying to create QMainWindow 
QMainWindow is not created, and the app just closed

После "возврата" (на самом деле он просто скрывается, а затем показывается) из reg_dlg и нажатия кнопки с принятием результата ничего не происходит! Он просто закрывает программу, но должен был показать QMainWindow!

Весь реальный код main.cpp:

#include "log_window_root.h"
#include "find_mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    log_window_root * log_wnd;
    find_mainwindow * find_wnd;

    log_wnd = new log_window_root();
    log_wnd->setWindowFlags(Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
    log_wnd->setModal(true);

    if(log_wnd->exec() == QDialog::Accepted)
    {
        find_wnd = new find_mainwindow();
        find_wnd->setWindowFlags(Qt::MSWindowsFixedSizeDialogHint);
        find_wnd->show();
    }
    return a.exec();
}

person SageCat    schedule 26.10.2019    source источник
comment
пожалуйста, загрузите весь код куда-нибудь. Кажется, что нет цикла событий, когда вы закрываете единственное оставшееся окно. Вы делаете это без экземпляра QGuiApplication?   -  person Soheil Armin    schedule 26.10.2019
comment
Хорошо, я загрузил весь код main.cpp. Другой тоже нужен? На самом деле, я только что создал проект QtWidget.   -  person SageCat    schedule 26.10.2019
comment
@SoheilArmin, извините, что вы имеете в виду, говоря, что цикла событий нет?   -  person SageCat    schedule 26.10.2019


Ответы (3)


Вы работаете немного за пределами Qt. Глядя на документацию:

Как правило, перед вызовом exec() взаимодействие с пользователем невозможно. В качестве особого случая перед вызовом exec() можно использовать модальные виджеты, такие как QMessageBox, поскольку модальные виджеты вызывают exec() для запуска локального цикла обработки событий.

Тестирование вашего кода на Mac OS даст вам страшное предупреждение

modalSession был завершен преждевременно - проверьте повторный вызов endModalSession

что показывает, что вы работаете по тонкому льду и ваш код сломается в любой момент.

Подумайте о том, чтобы переработать свой код так, чтобы MainWindow появлялся, а затем показывал ваши диалоги. Если вы хотите продолжить последовательность Dialog, удалите пару hide()/show() из on_btn_reg_clicked (эти вызовы испортят ваши циклы событий).

person Jens    schedule 26.10.2019
comment
Если он просто удалит hide()/show(), он потеряет желаемое поведение. Он может переместить log_dlg в невидимое место (по координатам). Или лучше переместить dlg_reg из log_dlg также на верхний уровень и организовать общее состояние наверху для обоих слоев dlgs и ввести специальный код возврата из log_dlg, чтобы снова запустить его на верхнем уровне. Может есть еще идеи - person oklas; 27.10.2019

QApplication завершает работу и закрывается, когда было закрыто последнее окно. Вы можете отказаться от этого, установив QApplication:: quitOnLastWindowClosed в false.

    QApplication a(argc, argv);
    a.setQuitOnLastWindowClosed(false);

Вы можете вернуть его в предыдущее состояние, когда ваша работа с этими диалогами будет завершена.

Как упоминал @Jens в другом ответе на ваш вопрос, в какой-то момент цикл будет безубыточным, и QApplication завершится даже до вызова a.exec(). Таким образом, вы также можете создать QWidget с нулевой шириной/высотой или вне экрана. как родитель ваших диалогов. QSplashScreen также является хорошим кандидатом для этого. Все ваши диалоги должны быть дочерними элементами экрана-заставки. Наконец, вы можете закончить заставку, вызвав QSplashScreen::finish.

person Soheil Armin    schedule 26.10.2019
comment
я написал это: QApplication a (argc, argv); a.setQuitOnLastWindowClosed (ложь); И ничего не изменилось. Делал как всегда: запускаю (начинается с dlg_log) -> Reg (создание dlg_reg) -> accept dlg_reg (возвращается к dlg_log) -> Enter (пытается создать QMainWindow) и ничего... - person SageCat; 26.10.2019
comment
Было ли приведенное выше объяснение плохим? Извините, если было :3 - person SageCat; 26.10.2019

[Повторная публикация из вопроса duplicate-closed, поскольку верхний баннер на это может привести к тому, что люди полностью пропустят этот вопрос, и ИМХО у этого нет хорошего ответа.]

Вот очень простой пример отображения диалога перед QMainWindow. В диалоговом окне просто представлена ​​возможность запуска основного приложения или нет. Ключевыми моментами являются то, что часть QDialog происходит до создания любых других виджетов (например, QMainWindow здесь), и приложение (main()) закрывается до этого, если это необходимо. Нет причин оставлять QDialog после его использования, поэтому я создаю его в стеке, а затем delete.


int main(int argc, char *argv[])
{
  QApplication a(argc, argv);
  QDialog *d = new QDialog();
  QPushButton *pbYes = new QPushButton("Would you like to play a game?", d);
  QPushButton *pbNo = new QPushButton("Get me out of here!", d);
  QObject::connect(pbYes, &QPushButton::clicked, [d]() { d->done(QDialog::Accepted); });
  QObject::connect(pbNo, &QPushButton::clicked, [d]() { d->done(QDialog::Rejected); });

  d->setLayout(new QVBoxLayout);
  d->layout()->addWidget(pbYes);
  d->layout()->addWidget(pbNo);

  const int ret = d->exec();
  delete d;

  if (ret == QDialog::Rejected)
    return 0;

  QMainWindow mw;
  mw.setCentralWidget(new QLabel("Welcome to the Game!", &mw));
  mw.show();

  return a.exec();
}
person Maxim Paperno    schedule 30.11.2019