Evgenii Legotckoi
Evgenii Legotckoi02 липня 2018 р. 14: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

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

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

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

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

```

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
d
  • dsfs
  • 26 квітня 2024 р. 11:56

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:80бали,
  • Рейтинг балів4
d
  • dsfs
  • 26 квітня 2024 р. 11:45

C++ - Тест 002. Константы

  • Результат:50бали,
  • Рейтинг балів-4
d
  • dsfs
  • 26 квітня 2024 р. 11:35

C++ - Тест 001. Первая программа и типы данных

  • Результат:73бали,
  • Рейтинг балів1
Останні коментарі
k
kmssr09 лютого 2024 р. 02:43
Qt Linux - Урок 001. Автозапуск програми Qt під Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий Кононенко05 лютого 2024 р. 09:50
Qt WinAPI - Урок 007. Робота з ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25 грудня 2023 р. 18:30
Boost - статичне зв&#39;язування в проекті CMake під Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJo25 грудня 2023 р. 16:38
Boost - статичне зв&#39;язування в проекті CMake під Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
Gvozdik19 грудня 2023 р. 05:01
Qt/C++ - Урок 056. Підключення бібліотеки Boost в Qt для компіляторів MinGW і MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Тепер обговоріть на форумі
G
Gar22 квітня 2024 р. 12:46
Clipboard Как скопировать окно целиком в clipb?
DA
Dr Gangil Academics20 квітня 2024 р. 14:45
Unlock Your Aesthetic Potential: Explore MSC in Facial Aesthetics and Cosmetology in India Embark on a transformative journey with an msc in facial aesthetics and cosmetology in india . Delve into the intricate world of beauty and rejuvenation, guided by expert faculty and …
a
a_vlasov14 квітня 2024 р. 13:41
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
Павел Дорофеев
Павел Дорофеев14 квітня 2024 р. 09:35
QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь
f
fastrex04 квітня 2024 р. 11:47
Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…

Слідкуйте за нами в соціальних мережах