Evgenij LegotskojSept. 1, 2019, 10:15 a.m.

Qt/C ++ - Tutorial 089. Buttons with absolute positioning inside QGraphicsView

Content

Considering the number of questions on the forum related to how to add buttons inside QGraphicsView, I decided to write a small tutorial on this topic. Moreover, there are various variations of the question. It can be a regular button, or even a mini-map, if the main QGraphicsView acts as a large map. In general, what exactly is a similar widget is not important. The bottom line is that there is the main QWidget, inside which the rest of the QWidget objects are located, which have absolute positioning inside this widget.

It will look like this.

QGraphicsView, внутри которого располагаются кнопки QPushButton с абсолютным позиционированием.

Introduction

QGraphicsView will be located in the widget of the main window and will be added through Qt Designer.

Whereas the remaining buttons will be added only through the program code. This is just one of those cases when I consider the use of a graphic designer is not the most convenient. Since in any case, you will often have to change the position of the buttons. Namely, with every resizing of the application window.

In general, the program code is quite simple, so immediately consider the header file of the application window, as well as the implementation file.

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class QPushButton;

class Widget : public QWidget
{
    Q_OBJECT

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

    virtual void resizeEvent(QResizeEvent *event) override;

private:
    void updateButtonsPosition();

    Ui::Widget *ui;

    // Buttons with absolute positioning
    QPushButton* m_topLeftButton;
    QPushButton* m_topRightButton;
    QPushButton* m_bottomLeftButton;
    QPushButton* m_bottomRightButton;
};

#endif // WIDGET_H

Widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    // Create all buttons with absolute positioning
    m_topLeftButton = new QPushButton("Top Left", ui->graphicsView);
    m_topRightButton = new QPushButton("Top Right", ui->graphicsView);
    m_bottomLeftButton = new QPushButton("Bottom Left", ui->graphicsView);
    m_bottomRightButton = new QPushButton("Bottom Right", ui->graphicsView);
    // Update button positions
    updateButtonsPosition();
}

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

void Widget::resizeEvent(QResizeEvent *event)
{
    Q_UNUSED(event);
    // We update the button positions for each resize event of the main window
    updateButtonsPosition();
}

void Widget::updateButtonsPosition()
{
    // The logic of changing the absolute positions of buttons inside QGraphicsView
    QRect graphicsViewGeometry = ui->graphicsView->geometry();
    m_topLeftButton->setGeometry({25,
                                  25,
                                  m_topLeftButton->geometry().width(),
                                  m_topLeftButton->geometry().height()});
    m_topRightButton->setGeometry({graphicsViewGeometry.width() - m_topRightButton->geometry().width() - 25,
                                   25,
                                   m_topRightButton->geometry().width(),
                                   m_topRightButton->geometry().height()});
    m_bottomLeftButton->setGeometry({25,
                                     graphicsViewGeometry.height() - m_bottomLeftButton->geometry().height() - 25,
                                     m_bottomLeftButton->geometry().width(),
                                     m_bottomLeftButton->geometry().height()});
    m_bottomRightButton->setGeometry({graphicsViewGeometry.width() - m_bottomRightButton->geometry().width() - 25,
                                      graphicsViewGeometry.height() - m_bottomRightButton->geometry().height() - 25,
                                      m_bottomRightButton->geometry().width(),
                                      m_bottomRightButton->geometry().height()});
}

Conclusion

Thus, you can set the absolute positioning for any other widgets in your program.

The important point is that you need to transfer the widget as the parent, inside which the created widget should be located. In this case, the parent object serves not only as a controller of memory leaks, that is, to automatically delete nested objects, but also to indicate the nesting of widgets in the application GUI.

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.
- company blog
Support the author Donate

Евгений, добрый день.
Вопрос не совсем по теме.
А почему вы объявили класс QPushButton в заголовочном файле таким образом, а не через include? Зачем include переносить в cpp?
В чём смысл?
Вопрос без "подковырки" - действительно интересно.

Добрый день, Александр.
Это Forward Declaration - Предварительное объявление. Позволяет объявить класс без подключения заголовочного файла в заголовочном файле другого класса.
Такое объявление может использоваться как для шаблонных аргментов, так и для указателей. Если переменная объявляется на стеке в заголовочном файле, то тогда да, приходится с использованием include объявлять.

По большей части Forward Declaration преследует две основные цели:

  • Оптимизация подключения заголовочных файлов при компиляции (ну тут всё понятно)
  • Разрешение циклических зависимостей, когда один класс имеет объявленные указатели на другой класс, а второй класс в свою очередь имеет указатели на первый класс. Если в обоих классах подключать заголовочный файлы через include в заголовочных файлах, то ничего не скомпилируется. А вот подключение заголовочных файлов в cpp и с Forward Declaration позволяют разрулить такую ситуацию.

Ну и у меня уже как-то на автомате такое делается, позволяет подключать в заголовочных файлах только самое необходимое, остальное уже в cpp файлах оставлять.

Comments

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

Let me recommend you the excellent hosting on which EVILEG is located.

For many years, Timeweb has been proving his stability.

For projects on Django I recommend VDS hosting

View Hosting
SN

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

  • Result:10points,
  • Rating points-10
k
  • knobu
  • Sept. 23, 2020, 2:34 a.m.

C++ - Test 006. Enumerations

  • Result:60points,
  • Rating points-1
k
  • knobu
  • Sept. 23, 2020, 2:21 a.m.

C++ - Test 005. Structures and Classes

  • Result:91points,
  • Rating points8
Last comments

Qt/C++ - Lesson 006. QSqlQueryModel – Tables in Qt with SQL-query

QSqlTableModel выполняет ряд стандартных операций для одной таблицы из базы данных. Поэтому там и реализован функционал по удалению и редактированию. QSqlQueryModel позволяет выполнить запр…
VB

Qt/C++ - Lesson 006. QSqlQueryModel – Tables in Qt with SQL-query

Добрый день. Хотел спросить вот что. Создал проект на основе QAbstractTableModel. В MainWindow cоответственно создал модель и связал с представлением. Поиск веду по списку элементов модели,…

QCheckBox в качестве делегата QTableView

До тех пор, пока у вас проект содержит только одну таблицу, или несколько то может быть. Когда их будет 1000 и чекбоксы в разных колонках, то без делегатов и переопределения возвращаемых ре…
D
  • Damir
  • Sept. 20, 2020, 3:34 p.m.

QCheckBox в качестве делегата QTableView

bool Node::setData(const QModelIndex& index, const QVariant& value, int role){ switch (index.column()) { case 0: switch (role) { case Qt::CheckStateRole:// <- т…
VB

Qt/C++ - Lesson 004. QSqlTableModel – How to present the table from database?

Почему-то такой метод для обновления не работает, который можно было бы применить в данном примере. То есть в представлении данные удаляются и обновляются, а в базе данных изменений не происходи…
Now discuss on the forum

как скрыть елемент с копии виджета

Можете попробовать установить парента для виджета. Когда вы создаёте виджет new errorWidget(error, this->ui->contentWidget); То вы передаёте ему parent объект. Полагаю, что эт…

Как в qml работать с динамически созданными потомками?

Спасибо) В Qt/С++ есть функция deleteLater, которую обычно используют, чтобы удалить объекты, которые наследованы от QObject . Она добавлена для того, чтобы не удалять такие…

Как в Qt в qmenu добавить scrollarea

Вот это наследованный класс меню. Но посути это обычное меню. #pragma once#include <QtWidgets>class TransMenu : public QMenu { Q_OBJECTpublic: TransMenu(QWidget* parent = …
VB

Как запустить программу с базой данных PostgreSQL на другом компьютере

Не требует никакую библиотеку, запускается на других компьютерах, где не установлена PostgreSQL, но создать элемент невозможно, тем более отредактировать или удалить.
p
  • prod1s
  • Sept. 24, 2020, 7:12 a.m.

через QT не могу открыть файл SQLite

Вирішення знайшов. Вказав замість назви БД об'єкт класу QSqlDataBase для QSqlQuery. QSqlQuery m_query = QSqlQuery(qSqlDataBase); Після двох днів пошуку рішення, все-таки знайшов…
About
Services
© EVILEG 2015-2020
Recommend hosting TIMEWEB