Поскольку писать на Qt начал недавно, то столкнулся со следующей проблемой: как правильно закрыть немодальное окно из главного окна.
Ниже пример: на главной форме есть кнопка "Создать окно". При нажатии на нее открывается дочернее немодальное окно. Всегда должен быть только 1 экземпляр этого окна. Если пользователь впервые нажал кнопку "Создать окно", то нужно создать его. Если он нажал второй раз, то сделать активным уже открытое окно. Если нажал крестик "Закрыть", то закрыть его.
Проблема в том, как контролировать, когда это окно открыто, а когда закрыто, чтобы не плодить кучу экземпляров этого окна, а держать только 1 экземпляр.
Последние дни перелопатил кучу примеров найденных в гугле и работает только 1 и то он очень громоздкий и похоже через заднее место.
Принцип работы:
— в классе главного окна (MainDialog) имеем указатель (pAnotherDialog) на наше дочернее окно (класс AnotherDialog)
— если пользователь нажал кнопку "Создать окно", то проверяем не создано ли оно уже (нашел единственный работающий способ проверить это: pAnotherDialog==NULL), и если оно уже создано (pAnotherDialog!=NULL) то делаем его активным), если не создано (pAnotherDialog==NULL), то создаем его.
Нашел единственный работающий способ: переопределить closeEvent(QCloseEvent *event) в AnotherDialog и отправлять в главное окно сигнал о том, пользователь пытается закрыть окно. В главном окне ловим этот сигнал в слоте и "насильно закрываем его" через accept() и обнуляем pAnotherDialog (чтобы потом знать, открыто окно или нет).
В общем способ громоздкий и чувствую, что решение должно быть намного проще.
Главный вопрос: как узнать в главном окне, открыто ли дочернее окно или нет? Единственное решение, которое я нашел, — это все время обнулять pAnotherDialog после закрытия окна (pAnotherDialog=NULL).
Повторю, что перелопатил кучу способов найденных в гугле и работает только этот.
Извиняюсь, что кидаю сюда кучу кода, комментить по строкам не буду, вроде все понятно.
Итак, структура проекта:
Headers:
anotherdialog.h // заголовочный файл дочернего окна
maindialog.h // заголовочный файл главного окна
Sources:
anotherdialog.cpp // код дочернего окна
main.cpp // код входа
maindialog.cpp // код главного окна
Forms:
anotherdialog.ui // форма дочернего окна
maindialog.ui // форма главного окна
Не буду постить main.cpp, т.к. там все по умолчанию. В maindialog.ui только 1 кнопка "Открыть окно". В maindialog.ui ничего нет.
maindialog.h:
#ifndef MAINDIALOG_H
#define MAINDIALOG_H
#include <QDialog>
#include "AnotherDialog.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainDialog; }
QT_END_NAMESPACE
class MainDialog : public QDialog
{
Q_OBJECT
public:
MainDialog(QWidget *parent = nullptr);
~MainDialog();
AnotherDialog* pAnotherDialog;
void showAnotherDialog(bool boolShow);
private slots:
void slotShowAnotherDialog();
void slotHideAnotherDialog();
private:
Ui::MainDialog *ui;
};
#endif // MAINDIALOG_H
maindialog.cpp :
#include "maindialog.h"
#include "ui_maindialog.h"
#include <QMessageBox>
#include <QDebug>
MainDialog::MainDialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::MainDialog)
{
ui->setupUi(this);
pAnotherDialog = NULL;
connect(ui->pushButton, &QPushButton::clicked, this, &this->slotShowAnotherDialog);
}
MainDialog::~MainDialog()
{
delete ui;
}
void MainDialog::showAnotherDialog(bool boolShow)
{
if (boolShow) {
if (pAnotherDialog==NULL) {
pAnotherDialog = new AnotherDialog(this);
pAnotherDialog->show();
}
else
pAnotherDialog->activateWindow();
connect(this->pAnotherDialog, AnotherDialog::signalHideAnotherDialog, this, this->slotHideAnotherDialog);
}
else {
if (pAnotherDialog != NULL) {
pAnotherDialog->accept();
pAnotherDialog = NULL;
}
}
}
void MainDialog::slotShowAnotherDialog()
{
showAnotherDialog(true);
}
void MainDialog::slotHideAnotherDialog()
{
showAnotherDialog(false);
}
anotherdialog.h :
#ifndef ANOTHERDIALOG_H
#define ANOTHERDIALOG_H
#include <QDialog>
namespace Ui {
class AnotherDialog;
}
class AnotherDialog : public QDialog
{
Q_OBJECT
public:
explicit AnotherDialog(QWidget *parent = nullptr);
~AnotherDialog();
protected:
void closeEvent(QCloseEvent *event) override;
signals:
void signalHideAnotherDialog();
private:
Ui::AnotherDialog *ui;
};
#endif // ANOTHERDIALOG_H
anotherdialog.cpp :
#include "anotherdialog.h"
#include "ui_anotherdialog.h"
#include <QCloseEvent>
AnotherDialog::AnotherDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::AnotherDialog)
{
ui->setupUi(this);
}
AnotherDialog::~AnotherDialog()
{
delete ui;
}
void AnotherDialog::closeEvent(QCloseEvent *event)
{
emit signalHideAnotherDialog();
event->ignore();
}
Главный вопрос: как контролировать открыто или закрыто дочернее окно, чтобы не плодить кучу экземпляров, а держать только 1 экземпляр?
Насколько это грамотный способ? Почему все так сложно и громоздко? Как сделать проще?
Какие есть еще способы?