Qt/C++ - Tutorial 081. How to make a base class for widgets using ui form files

Qt, ui, C++, Form

In some cases, you might need to create widget form classes that have a custom base class. That is, the form class of the widget will be inherited from your class, and not directly from QWidget , QDialog , or QMainWindow .

Naturally, for this, your custom class must be inherited from one of these three classes. But at the same time you will have your own base class for any specific functionality, no matter what. Do not make Holivar about how convenient or uncomfortable it is to use Qt Designer or it's better to write everything manually in the code. I know that some programmers do not accept the use of Qt Designer. But let us dwell on the fact that for me it is convenient, as for some other programmers.

Let's create two classes of FirstForm and SecondForm forms that will be inherited from the BaseWidget widget, which in turn is inherited from QWidget .

The appearance of the application window will be as follows.

Project structure

The Widget form class in this case is the application's base window, into which we will put the FirstForm and SecondForm widgets.

BaseWidget

In the BaseWidget base class, we define a virtual method that we will redefine in the inherited widgets. This will show us that this inheritance does work.

BaseWidget.h

Header file of the class.

#ifndef BASEWIDGET_H
#define BASEWIDGET_H

#include <QWidget>

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

    // Virtual base class method for validation
    virtual void methodFromBaseClass() const;
};

#endif // BASEWIDGET_H

BaseWidget.cpp

#include "BaseWidget.h"

#include <QDebug>

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

}

void BaseWidget::methodFromBaseClass() const
{
    // Outputting a message from a method
    qDebug() << "Base Class Method";
}

FirstForm

Both form classes will need to be generated using the class creation wizard. In this case, we choose QWidget as the base class.

After creating the class, you will need to fix some of the code, as well as fix the ui file.

After we create a new class, add a button to the form of this class.

FirstForm.h

#ifndef FIRSTFORM_H
#define FIRSTFORM_H

// #include <QWidget> It was
#include "BaseWidget.h" // Became

namespace Ui {
class FirstForm;
}

class FirstForm : public BaseWidget // Changed the base class
{
    Q_OBJECT

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

    // Overrided base class method
    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), // Perform the constructor of the base class
    ui(new Ui::FirstForm)
{
    ui->setupUi(this);
    // Connect the button to the virtual method
    connect(ui->pushButton, &QPushButton::clicked, this, &FirstForm::methodFromBaseClass);
}

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

// Implementing the Override Method
void FirstForm::methodFromBaseClass() const
{
    BaseWidget::methodFromBaseClass();
    qDebug() << "First Form Method";
}

FirstForm.ui

And here is the most interesting. To force the project to compile, you need to write a base class and information about inheritance in the UI file.

First, write the base class into the widget of the form class.

It was

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

Became

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

Secondly, write information about custom widgets with an indication of inheritance and the header file.

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

The result is the following UI file.

<?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>

SecondForm

Here is a similar program code.

Widget

Next, you need to add instances of these classes to the main application window. For clarity, we'll do it manually.

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;
}

Result

When compiling the application, we get a window, as shown at the beginning of the article. And in the console when you press the buttons, we get the following output.

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

Download project application

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.
Support the author Donate

Comments

Only authorized users can post comments.
Please, Log in or Sign up
N
June 25, 2019, 2:41 p.m.
Nico03

C++ - Test 001. The first program and data types

  • Result:40points,
  • Rating points-8
S
June 25, 2019, 9:16 a.m.
SabaNtuy

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:40points,
  • Rating points-8
SZ
June 24, 2019, 5:49 p.m.
Serg Zhi

C++ - Тест 003. Условия и циклы

  • Result:78points,
  • Rating points2
Last comments
June 24, 2019, 10:23 a.m.
Евгений Легоцкой

Хорошо, ну будут проблемы помимо того, что касается статей, то не стесняйтесь задавать вопросы на форуме.
МБ
June 24, 2019, 10:21 a.m.
Михаил Булатов

Извиняюсь, все работает(из-за невнимательности).
June 24, 2019, 9:52 a.m.
Евгений Легоцкой

Придётся делать ещё сигнал в дочернем qml и пробрасывать через коннекты и обработчики. А вообще нужно смотреть конкретный код и что вы пытаетесь сделать. Так что лучше будет, если вы зад...
June 21, 2019, 8:31 a.m.
Ruslan Polupan

Вот моя строка по которой все отлично сработало %cqtdeployer% -bin c:/CentralMposKeys/CentalMposKeys.exe -qmake c:/Qt/5.12.2/mingw73_64/bin/qmake.exe
June 21, 2019, 8:24 a.m.
Андрей Янкович

Возможно кому то пригодится сqtdeployer для windows работает точно так же как и для Linux разница лишь в команде запуска Linux: cqtdeployer Windows: %cqtdeployer...
Now discuss on the forum
June 25, 2019, 6:16 p.m.
Алексей Внуков

только через webengine, прямого апи у Яндекса нет, вроде что-то есть у гугла, сам только начал интересоваться этим вопросом
June 25, 2019, 5:05 p.m.
Михаиллл

Само заработало. Странно.
June 25, 2019, 2:32 p.m.
Михаиллл

Похоже глюк вебсокета. К другим вебсокетам подключаюсь.
June 25, 2019, 1:55 p.m.
Андрей Янкович

падало потому что boolStatus был на стеке метода, после завершения метода переменная убивалась, и на обращении к ней было падение.просто сделай вот так: connect(&t, &QTimer::timeou...
June 25, 2019, 10:55 a.m.
IscanderChe

По пункту 3 попытался переписать метод setData. В итоге комбобокс перестал работать. bool MySqlTableModel::setData(const QModelIndex& index, const QVariant& value, int /* role */){...
Looking for a Job?
10,000.00 руб. - 15,000.00 руб.
Нужен помощник для создания API.
Moscow, Moscow, Russia
25,000.00 руб. - 30,000.00 руб.
Разработчик Qt/C++
Barnaul, Altai Krai, Russia

For registered users on the site there is a minimum amount of advertising

EVILEG
About
Services
Join us
© EVILEG 2015-2019
Recommend hosting TIMEWEB