© EVILEG 2015-2018
Рекомендует хостинг
TIMEWEB

Qt/C++ - Урок 014. Динамическое создание виджетов в Qt

QPushButton, Dynamic widget, Динамический виджет, Qt

В сложных проектах может быть недостаточно наличия статических виджетов в интерфейсе программы, поскольку поступающая информация может изменяться ежесекундно. Следовательно поднимается вопрос о динамическом создании виджетов, например кнопок в компоновщике Qt.

В данном уроке описывается процесс динамического создания кнопок QPushButton, приёма сигналов от этих кнопок, а также последующее удаление этих кнопок из компоновщика Qt.

Программный код был написан в QtCreator 3.3.1 на основе Qt 5.4.1.

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

Описание структуры проекта:

  • DynamicButtons.pro - профайл;
  • mainwindow.h - заголовочный файл основного окна приложения;
  • mainwindow.cpp - исходный код окна;
  • main.cpp - основной исходный файл, с которого стартует приложение;
  • mainwindow.ui - формочка основного окна приложения;
  • qdynamicbutton.h - заголовочный файл класса обертки, который упрощает процесс работы с динамическими объектами в данном уроке;
  • qdynamicbutton.cpp - исходный файл класса обертки, который упрощает процесс работы с динамическими объектами в данном уроке.

mainwindow.ui

В данном уроке нам понадобится два слоя layout . В одном будут находиться все динамически создаваемые кнопки, а во втором слое будут находиться кнопки, которые будут отвечать за процесс создания и удаления динамических кнопок, а также поле lineEdit для отображения номера создаваемых кнопок.

Внешний вид приложения

Непосредственная работа будет осуществляться со следующими объектами формы окна приложения:

  • addButton - кнопка для добавления динамических кнопок;
  • deleteButton - кнопка для удаления динамических кнопок;
  • verticalLayout - слой для добавления динамических кнопок с вертикальной компоновкой;
  • lineEdit - поле для отображения номеров созданных кнопок.

qdynamicbutton.h

Заголовочный файл класса обёртки, который наследуется от класса QPushButton. В Данном классе объявляется статическая переменная, которая будет общей для всех объектов класса и будет являться счетчиков всех динамических кнопок, которые будут создаваться в данном приложении. Это необходимо для адекватного присвоения номеров каждой кнопки.

#ifndef QDYNAMICBUTTON_H
#define QDYNAMICBUTTON_H

#include <QPushButton>

class QDynamicButton : public QPushButton
{
    Q_OBJECT
public:
    explicit QDynamicButton(QWidget *parent = 0);
    ~QDynamicButton();
    static int ResID;   // Статическая переменная, счетчик номеров кнопок
    int getID();        // Функция для возврата локального номера кнопки


public slots:

private:
    int buttonID = 0;   // Локальная переменная, номер кнопки
};

#endif // QDYNAMICBUTTON_H

qdynamicbutton.cpp

В файле исходного кода класса-обёртки производится инициализация кнопки в её конструкторе, инициализация статической переменной, а также находится метод для возврата номера динамической кнопки.

#include "qdynamicbutton.h"

QDynamicButton::QDynamicButton(QWidget *parent) :
    QPushButton(parent)
{
    ResID++;            // Увеличение счетчика на единицу
    buttonID = ResID;   /* Присвоение кнопке номера, по которому будет производиться
                         * дальнейшая работа с кнопок
                         * */

}

QDynamicButton::~QDynamicButton()
{

}

/* Метод для возврата значения номера кнопки
 * */
int QDynamicButton::getID()
{
    return buttonID;
}

/* Инициализация статической переменной класса.
 * Статическая переменная класса должна инициализироваться в обязательном порядке
 * */
int QDynamicButton::ResID = 0;

mainwindow.h

В заголовочном файле требуется добавить только СЛОТы для обработки нажатий управляющих кнопок и СЛОТ для получения номера нажатой динамической кнопки.

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

/* My Includes */
#include <qdynamicbutton.h>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_addButton_clicked();    // СЛОТ-обработчик нажатия кнопки добавления
    void on_deleteButton_clicked(); // СЛОТ-обработчик нажатия кнопки удаления
    void slotGetNumber();           // СЛОТ для получения номера нажатой динамической кнопки

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H
mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    /* Для удобства работы слои разделены QSplitter
     * */
    ui->splitter->setStretchFactor(0,1);
    ui->splitter->setStretchFactor(1,0);
}

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

/* Метод для добавления динамической кнопки
 * */
void MainWindow::on_addButton_clicked()
{
    QDynamicButton *button = new QDynamicButton(this);  // Создаем объект динамической кнопки
    /* Устанавливаем текст с номером этой кнопки
     * */
    button->setText("Кнопочка " + QString::number(button->getID()));
    /* Добавляем кнопку в слой с вертикальной компоновкой
     * */
    ui->verticalLayout->addWidget(button);
    /* Подключаем сигнал нажатия кнопки к СЛОТ получения номера кнопки
     * */
    connect(button, SIGNAL(clicked()), this, SLOT(slotGetNumber()));
}

/* Метод для удаления динамической кнопки по её номеру
 * */
void MainWindow::on_deleteButton_clicked()
{
    /* Выполняем перебор всех элементов слоя, где располагаются динамические кнопки
     * */
    for(int i = 0; i < ui->verticalLayout->count(); i++){
        /* Производим каст элемента слоя в объект динамической кнопки
         * */
        QDynamicButton *button = qobject_cast<QDynamicButton*>(ui->verticalLayout->itemAt(i)->widget());
        /* Если номер кнопки соответствует числу, которое установлено
         * в lineEdit, то производим удаление данной кнопки
         * */
        if(button->getID() == ui->lineEdit->text().toInt()){
            button->hide();
            delete button;
        }
    }
}

/* СЛОТ для получения номера кнопки.
 * */
void MainWindow::slotGetNumber()
{
    /* Определяем объект, который вызвал сигнал
     * */
    QDynamicButton *button = (QDynamicButton*) sender();
    /* После чего устанавливаем номер кнопки в lineEdit,
     * который содержится в данной динамической кнопке
     * */
    ui->lineEdit->setText(QString::number(button->getID()));
    /* То есть номер кнопки устанавливается в поле lineEdit только тогда,
     * когда мы нажимаем одну из динамических кнопок, и этот номер соответствует
     * номеру нажатой кнопки
     * */
}

Итог

В результате у Вас должно получиться приложение, которое осуществляет динамическое создание и удаление кнопок. Работа приложения показана в видео приведённом ниже.

Комментарии

26 января 2017 г. 16:13
 QDynamicButton *button = qobject_cast<QDynamicButton*>(ui->verticalLayout->itemAt(i)->widget());
Поясните пожалуйста смысл этой строки.
26 января 2017 г. 16:22

В Qt элементы интерфейса имеют базовый класс QWidget . QDynamycButton наследован от QPushButton , который в свою очередь наследован в конечном итоге от QWidget . Из Layout`а указатели на объекты забираются в качестве указателей на объекты класса QWidget .

Таким образом, чтобы получить доступ к методам класса QDynamicButton , объектами которого являются в данном случае объекты, которые находятся в данном Layout`е, необходимо скастовать указатель из класса QWidget в QDynamicButton

Такие возможности языка C++ достигаются за счёт парадигмы полиморфизма. Пример полиморфизма с некоторыми пояснениями дан в этой статье .

Для Django рекомендую VDS-хостинг TIMEWEB

24 мая 2018 г. 0:36

Хм, не знаю как у других, а у меня отсутствует метод ui->splitter . Может быть потому что я на линухе сижу

24 мая 2018 г. 6:12

компонент был создан в графическом дизайнере, о чём говорит название объекта ui , в котором находится объект splitter.

Это не имеет зависимости на платформу

Для Django рекомендую VDS-хостинг TIMEWEB

Комментарии

Только авторизованные пользователи могут оставлять комментарии.
Пожалуйста, Авторизуйтесь или Зарегистрируйтесь
15 октября 2018 г. 21:36
Allyans .

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

  • Результат 60баллов,
  • Очки рейтинга-1
15 октября 2018 г. 11:25
Екатерина Самойлова

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

  • Результат 33баллов,
  • Очки рейтинга-10
15 октября 2018 г. 11:17
Екатерина Самойлова

C++ - Тест 006. Перечисления

  • Результат 80баллов,
  • Очки рейтинга4
Последние комментарии
17 октября 2018 г. 8:43
pasagir

Qt/C++ - Урок 006. QSqlQueryModel - Таблицы в Qt с помощью SQL-запросов

Не получается bool DataBase::insertDataIntoDB(QVariantList data){ QSqlQuery query(db); QString str; qDebug()<<"InsertInsertInsertInsertInsert"<<QThread::curre...
17 октября 2018 г. 7:09
Евгений Легоцкой

Qt/C++ - Урок 006. QSqlQueryModel - Таблицы в Qt с помощью SQL-запросов

Попробуйте передать инстанс базы данных в конструктор QSqlQuery QSqlQuery q(db);
16 октября 2018 г. 16:14
pasagir

Qt/C++ - Урок 006. QSqlQueryModel - Таблицы в Qt с помощью SQL-запросов

В Qt 5.11. при попытке вставить в БД запись выдает ошибку QSqlQuery::prepare: database not openQSqlDatabasePrivate::database: requested database does not belong to the calling thread. ...
10 октября 2018 г. 9:50
Евгений Легоцкой

Qt/C++ - Урок 083. Создание динамической библиотеки и подключение её в другой проект

Если и начинать писать о плагинах, то нужно тогда с Qt Creator начинать, там наверняка будет одинаковый принцип, но по Qt Creator хотя бы информация есть.
Сейчас обсуждают на форуме
17 октября 2018 г. 16:33
Allyans .

Работа с WinAPI в QT(изменение title bar)

Здравствуйте. Я хочу в своей программе изменить цвет title bar. Так как в qt нет не каких функций связаных с этим я искал в интернете ответ на мой вопрос и там советовали функцию SetSysColors(...
17 октября 2018 г. 13:39
Михаиллл

Настройка Qt Creator для Android

Здравствуйте. У меня установлены SDK, NDK. Но для компилятора не хватает arm-linux-android-elf-64bit, 86-linux-android-elf-64bit . Скажите пожалуйста как это исправить?
15 октября 2018 г. 12:45
Allyans .

QGraphicsItem change color

Хорошо)
11 октября 2018 г. 10:13
Arrow

Работа с WebView в QML

Нашел в чем проблема. Пишу на случай если кому-то попадется такое же счастье с WebView как и мне. Проблема как оказалась с Debug версией, так как в Release и Profile все работает (...
10 октября 2018 г. 12:49
Виталий Антипов

Кто что делает на Qt?

Работаем по локальной сети. Файл базы, схемы и фото лежат на сервере. Чтобы не было проблем при одновременной работе с одним файлом, все запросы обернул в транзакции, как указано в документаци...
Присоединяйтесь к нам в социальных сетях