- 1. Introduction
- 1. widget.h
- 2. Widget.cpp
- 2. Conclusion
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.
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.
Евгений, добрый день.
Вопрос не совсем по теме.
А почему вы объявили класс QPushButton в заголовочном файле таким образом, а не через include? Зачем include переносить в cpp?
В чём смысл?
Вопрос без "подковырки" - действительно интересно.
Добрый день, Александр.
Это Forward Declaration - Предварительное объявление. Позволяет объявить класс без подключения заголовочного файла в заголовочном файле другого класса.
Такое объявление может использоваться как для шаблонных аргментов, так и для указателей. Если переменная объявляется на стеке в заголовочном файле, то тогда да, приходится с использованием include объявлять.
По большей части Forward Declaration преследует две основные цели:
Ну и у меня уже как-то на автомате такое делается, позволяет подключать в заголовочных файлах только самое необходимое, остальное уже в cpp файлах оставлять.