PDA

View Full Version : Custom widget: paintEvent, can't change member variable



jforejtn
24th February 2015, 14:54
Hello,

I've created a custom widget. My goal was to simply draw a rectangle filled with color. I want the color to be changeable via setColor method, which is called from a slot of parent window object.

The problem is, that whenever paintEvent is called, the private member color is -- somehow -- initialized back to the value provided in constructor (Qt::white by default). That happens even though setColor method with a new color was called before the paintEvent. As a consequence, the widget is always painted in the same color that was provided in constructor.

I have also found a very similar unanswered question here:
http://stackoverflow.com/questions/10860709/calling-paintevent-reinitializes-member-variables

What is causing the problem? What should I do in order to enable the color switching?


ColorPreviewWidget.h:

#include <QWidget>
#include <QColor>

class ColorPreviewWidget : public QWidget
{
public:

ColorPreviewWidget
(
const QColor & preview_color = Qt::white,
QWidget *parent = 0
);

void setColor(const QColor& new_color);

protected:

void paintEvent(QPaintEvent* event);

private:

QColor color;
};

ColorPreviewWidget.cpp:

#include "ColorPreviewWidget.h"
#include <QPainter>
#include <QDebug>

ColorPreviewWidget::ColorPreviewWidget
(
const QColor & new_color,
QWidget *parent
)
:
QWidget(parent),
color(new_color)
{}

void ColorPreviewWidget::setColor(const QColor & new_color)
{
color = new_color;
qDebug() << "setColor : color = " << color;
// This debug message shows the right color (= new_color)
}

void ColorPreviewWidget::paintEvent(QPaintEvent* e)
{
qDebug() << "paintEvent : color = " << color;
// This debug message shows the wrong, default color, over
// and over again!
QPainter painter(this);
painter.fillRect(0, 0, size().width(), size().height(), color);
}

d_stranz
24th February 2015, 17:34
There is nothing wrong that I can see with the code you have posted. What I guess is probably wrong is in the way you are using this class. Are you sure that you are setting the new color on the SAME instance that is being used in the painting? Did you maybe accidentally create a local variable with the same name as your widget's instance that is hiding the one you think is being painted?

jforejtn
24th February 2015, 18:03
Further desperate investigation revealed following:

When i print &color (i.e. address of the private member color) inside different functions, I get two different results:

Both ColorPreviewWidget::ColorPreviewWidget and ColorPreviewWidget::paintEvent give

&color = 0x90753e4d60

while ColorPreviewWidget::setColor gives

&color = 0x907301b4a0

Added after 20 minutes:


There is nothing wrong that I can see with the code you have posted. What I guess is probably wrong is in the way you are using this class. Are you sure that you are setting the new color on the SAME instance that is being used in the painting? Did you maybe accidentally create a local variable with the same name as your widget's instance that is hiding the one you think is being painted?

You guess right. I've been working with two different instances of the custom widget, painting one and changing color to another. Thanks for your answer. Problem solved.

d_stranz
25th February 2015, 03:17
We've all been there and done that.