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
How to become an author?

Contribute to the evolution of the EVILEG community.

Learn how to become a site author.

Learn it
Donate

Good day, Dear Users!!!

I am Evgenii Legotckoi, developer of EVILEG. And it is my hobby project, which helps to learn programming another programmers and developers

If the site helped you, and you want also support the development of the site, than you can donate by following ways

PayPalYandex.Money
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
KA

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

  • Result:78points,
  • Rating points2
R

C++ - Test 002. Constants

  • Result:75points,
  • Rating points2
R

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

  • Result:73points,
  • Rating points1
Last comments
V

Django - Tutorial 027. Implementation Google reCAPTCHA

Спасибо. Только использую декоратор не в urls.py а перед views
R

Qt WinAPI - Lesson 001. How to collect all DLL, which used in Qt project?

Вы меня не совсем правильно поняли, но все равно спасибо, принял все к сведению. Все сделал как вы сказали, все отлично работает, еще раз огромнейшее спасибо) Разве что только что были опять про…

Qt WinAPI - Lesson 001. How to collect all DLL, which used in Qt project?

Стоило перед использованием что ли инструкцию прочитать https://www.cyberforum.ru/blogs/131347/blog2457.html "После сборки при запуске требовались dll," Ясное дело стоило задепло…
R
R

Qt WinAPI - Lesson 001. How to collect all DLL, which used in Qt project?

Да, собралось. После сборки при запуске требовались dll, перекинул всю папки bin, plugins(не знаю как можно было сделать более умно). Как я понял в первой строке путь к екзешнику вставляю, втор…
Now discuss on the forum

QML+QtGraphicalEffects

да, сборку делал без параметра поиска qml, хотя dll QtGraphicalEffects он подтягивает, когда я добавил всю папку QtGraphicalEffects в проект - то заработало, похоже что именно qml-файлов ему не …

Не работают слоты/сигналы

и посмотрите работу с потоками в Qt, там подробно описано как передавать данные с одного в потока в другой при помощи сигналов и слотов

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

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

Qt C++ и Python

Красиво/некрасиво - это скорее моё личное отношение. Если есть возможность ограничить количество интсрументов, то лучше ограничить. Но не зацикливайтесь на этом. Если у вас есть скрипты Py…

Qt + OpenGL glDeleteVertexArrays

Я не уверен, поскольку с OpenGL очень мало работал. Но может быть OpenGL контекст виджета нужно переинициализовывать. И ещё виджет стоит удалять через метод deleteLater() а не п…
About
Services
© EVILEG 2015-2020
Recommend hosting TIMEWEB