I am trying to paint a rectangle at the mouse location every time it is clicked.
Currently, the setup is as follows:
TableMaker
is my main window and was mostly generated in Qt Designer.
I have subclassed a QWidget
, RenderArea
, and added it inside a frame in my ui
.
I currently have TableMaker::mousePressEvent
calling a function in renderArea
that creates a new QRect
and keeps a reference to it in a vector.
So far everything up to this point works, and when I check in a debugger it is indeed creating these QRect
s and storing them on each mouse press.
However, I tried overriding paintEvent
for renderArea
so that it will update and draw these new QRect
s, but it is never being called.
I feel like I have misunderstood how painting and the associated events work, and who should actually have ownership of the overridden paintEvent
.
Below is the code for the 2 classes TableMaker
and RenderArea
:
main.cpp:
#include "TableMaker.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TableMaker w;
w.show();
return a.exec();
}
TableMaker.cpp:
#include "TableMaker.h"
TableMaker::TableMaker(QWidget *parent) : QMainWindow(parent)
{
ui.setupUi(this);
renderArea = new RenderArea;
QGridLayout* drawAreaLayout = new QGridLayout;
drawAreaLayout->addWidget(renderArea);
ui.tentFrame->setLayout(drawAreaLayout);
}
void TableMaker::mousePressEvent(QMouseEvent* e) {
renderArea->addNewTable(e->pos());
renderArea->update();
}
TableMaker::~TableMaker()
{}
TableMaker.h:
#include <QtWidgets/QMainWindow>
#include <QtWidgets>
#include <QtGui>
#include "ui_TableMaker.h"
#include "RenderArea.h"
class TableMaker : public QMainWindow
{
Q_OBJECT
public:
TableMaker(QWidget *parent = nullptr);
void mousePressEvent(QMouseEvent* e) override;
~TableMaker();
private:
RenderArea* renderArea;
QLabel* statusMsg = new QLabel;
Ui::TableMakerClass ui;
};
renderArea.cpp:
#include "RenderArea.h"
RenderArea::RenderArea(QWidget* parent): QWidget(parent) {
brush.setColor(tableColor);
pen.setBrush(brush);
}
void RenderArea::addNewTable(QPoint p) {
QRect* rec = new QRect(p, QSize(100, 100));
recs.push_back(rec);
this->update();
}
QSize RenderArea::sizeHint() const {
return QSize(100, 100);
}
void RenderArea::paintEvent(QPaintEvent* e) {
QWidget::paintEvent(e);
QPainter p(this);
p.setPen(pen);
p.setBrush(brush);
for (QRect* r : recs) {
p.drawRect(*r);
}
}
renderArea.h:
#include <Qtwidgets>
#include "tableWidget.h"
class RenderArea : public QWidget {
Q_OBJECT
public:
explicit RenderArea(QWidget* parent = nullptr);
void addNewTable(QPoint p);
protected:
QSize sizeHint() const override;
void paintEvent(QPaintEvent* e) override;
private:
QColor tableColor = QColor(0, 0, 255);
QBrush brush;
QPen pen;
QVector<QRect*> recs;
};
How do paintEvent
s / painting work? I have tried reading the docs about QPaintEvent
and it seems like I am overriding paintevent
correctly.
Another post on here mentions that sizeHint
must be reimplemented, but as you can see below, I have done that and it still does not work.
Explanation:
paintEvent
does get called, you can check that using a qDebug()
:
void RenderArea::paintEvent(QPaintEvent* e)
{
QWidget::paintEvent(e);
QPainter p(this);
p.setPen(pen);
p.setBrush(brush);
//outputs: Qt::NoBrush
qDebug()<<p.brush().style();
//outputs: "#0000ff"
qDebug()<<p.brush().color().name();
//outputs: "#0000ff"
qDebug()<<p.pen().color().name()<<"\n";
for (QRect* r : recs)
{
//list gets bigger with every mouse press
qDebug()<<r;
p.drawRect(*r);
}
}
The problem is that the rectangles are being drawn with a brush that has no style set.
From Qt Documentation: QBrush Class:
The brush style() defines the fill pattern using the Qt::BrushStyle enum. The default brush style is Qt::NoBrush (depending on how you construct a brush). This style tells the painter to not fill shapes.
Solution:
You just need a small addition to RenderArea
ctor:
RenderArea::RenderArea(QWidget* parent): QWidget(parent)
{
//set brush style
brush.setStyle(Qt::SolidPattern);
brush.setColor(tableColor);
pen.setBrush(brush);
}
Result: