Evgenii Legotckoi
03 липня 2018 р. 00:24

Qt/C++ - Підручник 081. Як створити базовий клас для віджетів за допомогою файлів форм інтерфейсу користувача

У деяких випадках може знадобитися створювати класи форм віджетів, які мають кастомний базовий клас. Тобто клас форми віджету буде успадкований від вашого класу, а не безпосередньо від QWidget , QDialog або QMainWindow .

Звичайно, для цього ваш кастомний клас повинен бути успадкований від одного з цих трьох класів. Але при цьому у вас буде власний базовий клас для якогось специфічного функціоналу, не важливо для якого. Не робитимемо Холівар про те, наскільки зручно чи незручно використовувати Qt Designer або краще писати все вручну в коді. Знаю, що деякі програмісти не приймають використання Qt Designer. Але зупинимося на тому, що для мене він зручний, як і для інших програмістів.

Створимо два класи форм FirstForm і SecondForm , які будуть успадковані від віджету BaseWidget , який у свою чергу успадковується від QWidget .

Зовнішній вигляд вікна програми буде таким.


Структура проекту

Клас форми Widget у цьому випадку буде базовим вікном програми, в яку ми помістимо віджети FirstForm та SecondForm .

BaseWidget

У базовому класі BaseWidget визначимо віртуальний метод, який перевизначатимемо у спадкових віджетах. Це покаже нам те, що це успадкування дійсно працює.

BaseWidget.h

Заголовний файл класу.

#ifndef BASEWIDGET_H
#define BASEWIDGET_H

#include <QWidget>

class BaseWidget : public QWidget
{
    Q_OBJECT
public:
    explicit BaseWidget(QWidget *parent = nullptr);

    // Виртуальный метод базового класса для проверки
    virtual void methodFromBaseClass() const;
};

#endif // BASEWIDGET_H

BaseWidget.cpp

#include "BaseWidget.h"

#include <QDebug>

BaseWidget::BaseWidget(QWidget *parent) : QWidget(parent)
{

}

void BaseWidget::methodFromBaseClass() const
{
    // Вывод сообщения из метода
    qDebug() << "Base Class Method";
}

FirstForm

Обидва класи форми необхідно буде згенерувати за допомогою візарду створення класів. При цьому виберемо як базовий клас QWidget .

Після створення класу потрібно буде виправити частину коду, а також виправити файл ui.

Після того як створимо новий клас, додамо кнопку на форму цього класу.

FirstForm.h

#ifndef FIRSTFORM_H
#define FIRSTFORM_H

// #include <QWidget> Было
#include "BaseWidget.h" // Стало

namespace Ui {
class FirstForm;
}

class FirstForm : public BaseWidget // Изменили базовый класс
{
    Q_OBJECT

public:
    explicit FirstForm(QWidget *parent = nullptr);
    ~FirstForm();

    // Переопределили метод базового класса
    virtual void methodFromBaseClass() const override;

private:
    Ui::FirstForm *ui;
};

#endif // FIRSTFORM_H

FirstForm.cpp

#include "FirstForm.h"
#include "ui_FirstForm.h"

#include <QDebug>

FirstForm::FirstForm(QWidget *parent) :
    BaseWidget(parent), // Выполним конструктор базового класса
    ui(new Ui::FirstForm)
{
    ui->setupUi(this);
    // Подключим кнопку к виртуальному методу
    connect(ui->pushButton, &QPushButton::clicked, this, &FirstForm::methodFromBaseClass);
}

FirstForm::~FirstForm()
{
    delete ui;
}

// Реализация переопределённого метода
void FirstForm::methodFromBaseClass() const
{
    BaseWidget::methodFromBaseClass();
    qDebug() << "First Form Method";
}

FirstForm.ui

А ось тут найцікавіше. Щоб змусити проект компілюватися, потрібно прописати базовий клас та інформацію про наслідування в UI-файлі.

По-перше, прописати базовий клас в тег widget класу форми.

Було

<widget class="QWidget" name="FirstForm">
    ...
</widget>

Стало

<widget class="BaseWidget" name="FirstForm">
    ...
</widget>

По-друге прописати інформацію про кастомні віджети із зазначенням успадкування та заголовного файлу.

<customwidgets>
 <customwidget>
  <class>BaseWidget</class>
  <extends>QWidget</extends>
  <header>BaseWidget.h</header>
  <container>1</container>
 </customwidget>
</customwidgets>

В результаті отримаємо наступний UI-файл.

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>FirstForm</class>
 <widget class="BaseWidget" name="FirstForm">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <layout class="QGridLayout" name="gridLayout">
   <item row="0" column="0">
    <widget class="QPushButton" name="pushButton">
     <property name="text">
      <string>First Form Button</string>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <customwidgets>
  <customwidget>
   <class>BaseWidget</class>
   <extends>QWidget</extends>
   <header>BaseWidget.h</header>
   <container>1</container>
  </customwidget>
 </customwidgets>
 <resources/>
 <connections/>
</ui>

Друга форма

Тут є аналогічний програмний код.

Віджет

Далі потрібно додати інстанси даних класів у головне вікно програми. Для наочності зробимо це вручну.

Widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

class FirstForm;
class SecondForm;

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
    FirstForm *m_firstForm;
    SecondForm *m_secondForm;
};

#endif // WIDGET_H

Widget.cpp

#include "Widget.h"
#include "ui_Widget.h"

#include "FirstForm.h"
#include "SecondForm.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    m_firstForm = new FirstForm(this);
    m_secondForm = new SecondForm(this);

    ui->verticalLayout->addWidget(m_firstForm);
    ui->verticalLayout->addWidget(m_secondForm);
}

Widget::~Widget()
{
    delete ui;
}

Результат

При компілювання програми отримаємо вікно, як було показано на початку статті. А в консоль при натисканні клавіш отримаємо наступний висновок.

Base Class Method
First Form Method
Base Class Method
Second Form Method

Скачати проект програми

Вам це подобається? Поділіться в соціальних мережах!

c
  • 31 серпня 2019 р. 15:13
  • (відредаговано)

```

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up