Evgenii Legotckoi
Sept. 1, 2019, 8:15 p.m.

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

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

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3.  
  4. #include <QWidget>
  5.  
  6. namespace Ui {
  7. class Widget;
  8. }
  9.  
  10. class QPushButton;
  11.  
  12. class Widget : public QWidget
  13. {
  14. Q_OBJECT
  15.  
  16. public:
  17. explicit Widget(QWidget *parent = nullptr);
  18. ~Widget();
  19.  
  20. virtual void resizeEvent(QResizeEvent *event) override;
  21.  
  22. private:
  23. void updateButtonsPosition();
  24.  
  25. Ui::Widget *ui;
  26.  
  27. // Buttons with absolute positioning
  28. QPushButton* m_topLeftButton;
  29. QPushButton* m_topRightButton;
  30. QPushButton* m_bottomLeftButton;
  31. QPushButton* m_bottomRightButton;
  32. };
  33.  
  34. #endif // WIDGET_H
  35.  

Widget.cpp

  1. #include "widget.h"
  2. #include "ui_widget.h"
  3. #include <QPushButton>
  4.  
  5. Widget::Widget(QWidget *parent) :
  6. QWidget(parent),
  7. ui(new Ui::Widget)
  8. {
  9. ui->setupUi(this);
  10. // Create all buttons with absolute positioning
  11. m_topLeftButton = new QPushButton("Top Left", ui->graphicsView);
  12. m_topRightButton = new QPushButton("Top Right", ui->graphicsView);
  13. m_bottomLeftButton = new QPushButton("Bottom Left", ui->graphicsView);
  14. m_bottomRightButton = new QPushButton("Bottom Right", ui->graphicsView);
  15. // Update button positions
  16. updateButtonsPosition();
  17. }
  18.  
  19. Widget::~Widget()
  20. {
  21. delete ui;
  22. }
  23.  
  24. void Widget::resizeEvent(QResizeEvent *event)
  25. {
  26. Q_UNUSED(event);
  27. // We update the button positions for each resize event of the main window
  28. updateButtonsPosition();
  29. }
  30.  
  31. void Widget::updateButtonsPosition()
  32. {
  33. // The logic of changing the absolute positions of buttons inside QGraphicsView
  34. QRect graphicsViewGeometry = ui->graphicsView->geometry();
  35. m_topLeftButton->setGeometry({25,
  36. 25,
  37. m_topLeftButton->geometry().width(),
  38. m_topLeftButton->geometry().height()});
  39. m_topRightButton->setGeometry({graphicsViewGeometry.width() - m_topRightButton->geometry().width() - 25,
  40. 25,
  41. m_topRightButton->geometry().width(),
  42. m_topRightButton->geometry().height()});
  43. m_bottomLeftButton->setGeometry({25,
  44. graphicsViewGeometry.height() - m_bottomLeftButton->geometry().height() - 25,
  45. m_bottomLeftButton->geometry().width(),
  46. m_bottomLeftButton->geometry().height()});
  47. m_bottomRightButton->setGeometry({graphicsViewGeometry.width() - m_bottomRightButton->geometry().width() - 25,
  48. graphicsViewGeometry.height() - m_bottomRightButton->geometry().height() - 25,
  49. m_bottomRightButton->geometry().width(),
  50. m_bottomRightButton->geometry().height()});
  51. }
  52.  

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.

Александр Панюшкин
  • Sept. 2, 2019, 12:39 a.m.

Евгений, добрый день.
Вопрос не совсем по теме.
А почему вы объявили класс 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
  • Last comments
  • Evgenii Legotckoi
    March 9, 2025, 9:02 p.m.
    К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
  • VP
    March 9, 2025, 4:14 p.m.
    Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…
  • ИМ
    Nov. 22, 2024, 9:51 p.m.
    Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
  • Evgenii Legotckoi
    Oct. 31, 2024, 11:37 p.m.
    Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
  • A
    Oct. 19, 2024, 5:19 p.m.
    Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html