QDialog се затваря сам, как мога да го поправя?

Имената на класовете ми са като (какво прави)_(тип), например: reg_QDialog

Ето код на изпълняващ се dlg и ако е прието, създава QMainWindow:

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

log_dlg има 2 btns: "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 и натискане на btn с резултат за приемане, не прави нищо! Той просто затваря програмата, но трябваше да покаже 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(). Като специален случай, модалните уиджети като QMessageBox могат да се използват преди извикването на exec(), тъй като модалните уиджети извикват 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 спомена в другия отговор на вашия въпрос, това ще прекъсне evenloop в даден момент и QApplication излиза, преди дори да бъде извикан a.exec(). Така че можете също да създадете QWidget с нулева ширина/височина или извън екрана като родител на вашите диалози. QSplashScreen също е добър кандидат за това. Всичките ви диалози трябва да са вашите деца на началния екран. Най-накрая можете да завършите своя начален екран, като извикате QSplashScreen::finish.

person Soheil Armin    schedule 26.10.2019
comment
написах това: QApplication a(argc, argv); a.setQuitOnLastWindowClosed(false); И нищо не се промени. Направих както винаги: стартирам (започва с dlg_log) -› Reg (създава dlg_reg) -› приемам dlg_reg (връщам се към dlg_log) -› Enter (опитвам се да създам QMainWindow) и нищо... - person SageCat; 26.10.2019
comment
Лошо ли беше горното обяснение? Съжалявам, ако е било :3 - person SageCat; 26.10.2019

[Повторно публикуване от дублиране-затворен въпрос от горния банер на може да накара хората да пропуснат този въпрос изцяло и IMHO този няма добър отговор.]

Ето един много прост пример за показване на диалогов прозорец преди 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