garbart
garbart

Reputation: 485

Error with drawing point on QLabel

I'm trying to draw on QLabel in Qt like this:

paintscene.h:

class PaintScene : public QWidget
{
    Q_OBJECT
public:
    PaintScene(QWidget* parent = NULL);

    QVector<QLabel*> _layers;
    QColor _color;
    int _width;

    void mousePressEvent(QMouseEvent* event);

private slots:
    void updateWidth();
};

paintscene.cpp:

PaintScene::PaintScene(QWidget* parent) : QWidget(parent)
{
    _width = 10;
    _color = Qt::red;
    QLabel* inital = new QLabel(this);
    inital->setStyleSheet("QLabel { background-color : white; }");
    _layers.push_back(inital);

    QGridLayout* layout = new QGridLayout();
    layout->addWidget(inital, 1, 1, 1, 1);
    this->setLayout(layout);
}

void PaintScene::mousePressEvent(QMouseEvent *event)
{
    QImage tmp = _layers.back()->pixmap()->toImage();
    QPainter painter(&tmp);
    QPen paintpen(_color);
    paintpen.setWidth(_width);
    painter.setPen(paintpen);
    painter.drawPoint(event->x(), event->y());
    _layers.back()->setPixmap(QPixmap::fromImage(tmp));
}

The list is needed because I want to implement the work with layers (QLabel - a separate layer).

However, I get an error, the program terminates. The error occurs on the line QImage tmp = _layers.back()->pixmap()->toImage();.

What makes this happen? How can this be fixed? Maybe for a layer to use something different, not QLabel?

Upvotes: 1

Views: 178

Answers (2)

eyllanesc
eyllanesc

Reputation: 243955

@Jeremy Friesner is right about the reason for the error, not having a QPixmap this will be null, in my answer I will show a possible solution

void PaintScene::mousePressEvent(QMouseEvent *event)
{
    QLabel *label = _layers.back();
    const QPixmap *pix= label->pixmap();
    QPixmap pixmap;
    if(pix)
        pixmap =  *pix;
    else{
        pixmap = QPixmap(label->size());
        pixmap.fill(Qt::transparent);
    }
    QPainter painter(&pixmap);
    QPen paintpen(_color);
    paintpen.setWidth(_width);
    painter.setPen(paintpen);
    painter.drawPoint(event->pos());
    painter.end();
    label->setPixmap(pixmap);
}

enter image description here

Upvotes: 1

Jeremy Friesner
Jeremy Friesner

Reputation: 73081

From the Qt docs for QLabel::pixmap():

This property holds the label's pixmap
If no pixmap has been set this will return 0.

... so when you do this:

QImage tmp = _layers.back()->pixmap()->toImage();

pixmap() is returning NULL (because the QLabel has never had any QPixmap set on it yet), and then you try to dereference that NULL pointer to call toImage() on it, hence the crash.

To avoid crashing, don't try to create a QImage from a NULL QPixmap pointer.

I suspect you wanted to be calling grab() instead of pixmap() -- grab() will create a QPixmap for you that contains the visual appearance of the QLabel. However, an even better approach would be to avoid messing about with QPixmaps at all; instead, make your own subclass of the QLabel class, and override its paintEvent(QPaintEvent *) method to first call up to QLabel::paintEvent(e) and then use a QPainter to draw the additional point afterwards. That will be easier to implement and also more efficient at runtime.

Upvotes: 1

Related Questions