Russian Qt Forum
Май 06, 2024, 23:24 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Закрыть немодальное окно из главного  (Прочитано 1486 раз)
theminister
Новичок

Offline Offline

Сообщений: 1


Просмотр профиля
« : Ноябрь 27, 2020, 10:14 »

Поскольку писать на 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 экземпляр?

Насколько это грамотный способ? Почему все так сложно и громоздко? Как сделать проще?

Какие есть еще способы?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #1 : Ноябрь 27, 2020, 12:03 »

Штатное средство - QPointer
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.054 секунд. Запросов: 23.