arqam arqam - 11 months ago 62
C++ Question

Qt : Having a single instance of QPainter object in a class

I am doing a project in

Qt
and there is an object
QPainter
which is declared as :

QPainter painter(this);


Where this points to the present class. My problem is that I need to declare this object such that it is accessible to the entire class functions.

If I declare it inside the constructor then its scope is not valid for other functions, and I cannot declare outside all function in my
.cpp
file as
this
variable doesn't make any sense.

So how can I declare my object such that it is accessible to all the functions?

Edit : Painter Code :

void MainWindow :: paintEvent(QPaintEvent * e)
{
QMainWindow::paintEvent(e);
if(1)
{
QPainter painter(this);
QPen paintpen(Qt::red);
paintpen.setWidth(5);
QPoint p1;
p1.setX(mFirstX);
p1.setY(mFirstY);
painter.setPen(paintpen);
painter.drawPoint(p1);
}

}


Mouse Event Code :

void MainWindow :: mousePressEvent(QMouseEvent *e)
{
mFirstX=0;
mFirstY=0;
mFirstClick=true;
mpaintflag=false;

if(e->button() == Qt::LeftButton)
{
//store 1st point
if(1)
{
mFirstX = e->x();
mFirstY = e->y();
mFirstClick = false;
mpaintflag = true;
qDebug() << "First image's coordinates" << mFirstX << "," << mFirstY ;
update();

}

}
}


PROBLEM : I want to create the point but I don't want it to disappear from the widget(mainWindow). Here since the object is created during the paintEvent method each time the point that I am drawing is disappearing when the next point is drawn.

And if I declare it outside the paintEvent then I get the following error:

QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::setPen: Painter not active

Answer Source

In general, declaring the QPainter object globally is not a good idea. It is better to construct it in the QWidget::paintEvent (where it will be active) and, as @Mat said, pass it (by reference) to the functions that need it.

In your particullar case the point disappears because the widget is redrawn, not because the QPainter is destroyed. So the strategy should be to create and manage a buffer of points. Add a point to the buffer in a mouse event, e.g. QWidget::mousePressEvent (there do some management too, e.g. limiting the number of points) and in the paint event - paint all the points from the buffer.

Here is an oversimplified example which could easily be adapted for your specific purpose:

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMouseEvent>
#include <QPaintEvent>
#include <QPainter>

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = nullptr);

protected:
    void mousePressEvent(QMouseEvent *event);
    void paintEvent(QPaintEvent *event);

private:
    QList<QPoint> m_points;
};

#endif // MAINWINDOW_H

MainWindow.cpp

#include "MainWindow.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    QPalette p = QPalette();

    p.setColor(QPalette::Window, Qt::white);

    setPalette(p);
    setAutoFillBackground(true);
    resize(400, 400);
}

void MainWindow::mousePressEvent(QMouseEvent *event)
{
    m_points.append(event->pos());

    update();
}

void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    painter.setClipping(true);
    painter.setClipRect(event->rect());

    painter.setPen(QPen(Qt::red, 5));

    foreach (QPoint point, m_points) { painter.drawPoint(point); }
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download