Reputation: 6147
How do I properly add a property to a custom control, which when changed triggers the paint event? The property only accepts an integer value of 0, 1 or 2.
The setter of the property would be called setPattern, so an example use would be setPattern(0).
This property value will eventually be used to control the pattern drawn in the paint event.
labelheader.h
#ifndef LABELHEADER_H
#define LABELHEADER_H
#include <QLabel>
class LabelHeader : public QLabel
{
Q_OBJECT
public:
explicit LabelHeader(QWidget *parent = nullptr);
explicit LabelHeader(const QString &text, QWidget *parent = nullptr);
signals:
public slots:
// QWidget interface
protected:
void paintEvent(QPaintEvent *event);
};
#endif // LABELHEADER_H
labelheader.cpp
#include "labelheader.h"
#include <QPainter>
LabelHeader::LabelHeader(QWidget *parent) :
QLabel(parent)
{
}
LabelHeader::LabelHeader(const QString &text, QWidget *parent) :
QLabel(text, parent)
{
}
void LabelHeader::paintEvent(QPaintEvent *event)
{
// calculate font width
QFontMetrics metrics(font());
int text_width = metrics.boundingRect(text()).width();
// calculate dimensions
int y = height() * 0.5;
int x = text_width + 4;
// create pattern
QPixmap px(4, 4);
px.fill(Qt::transparent);
QPainter pattern_painter(&px);
// Create ashed 3 dots
pattern_painter.setPen(Qt::NoPen);
pattern_painter.setBrush(QBrush(palette().color(QPalette::WindowText), Qt::SolidPattern));
pattern_painter.drawRect(0, 0, 1, 1);
pattern_painter.drawRect(2, 2, 1, 1);
// draw
QPainter painter(this);
// Draw dashed 3 dots
painter.drawTiledPixmap(x, y-2, width()-x, 5, px);
// Draw solid line
//painter.drawLine(x,y,width(),y);
QLabel::paintEvent(event);
}
Upvotes: 2
Views: 1383
Reputation: 8399
To accomplish what you need you do not actually need QProperty, but a private attribute of your LabelHeader
class. Here is a step-by-step guide, covering all your requirements:
In LabelHeader.h add:
enum PatternType {
PatternOne = 0,
PatternTwo,
PatternThree
};
In LabelHeader.h add:
private:
PatternType m_pattern;
m_pattern
and select Refactor->Create Getter and Setter Member FunctionsIn the implementation of the setter invoke a paintEvent
by calling update()
, but only if the new pattern is different than the current one:
if (m_pattern == pattern)
return;
m_pattern = pattern;
update();
In the constructor add m_pattern
to the initializer list to set its value by default
Use the value in the LabelHeader::paintEvent
to draw the corresponding pattern
// draw tiled pixmap
QPainter painter(this);
switch (m_pattern) {
case PatternOne:
painter.drawTiledPixmap(x, y-2, w, 5, px);
break;
case PatternTwo:
painter.drawTiledPixmap(x, y, w, 5, px);
break;
default:
painter.drawTiledPixmap(x, y+2, w, 5, px);
}
I have extended the example from this answer to cover your current requirements as well. The full code is available on GitHub.
Regarding the use of Q_PROPERTY
, here is an important explanation kindly provided by @KubaOber:
Q_PROPERTY is a Qt idiom used to both convey a meaning to a human reader, and expose the property as such to the metatype system, making it easily scriptable from QML, etc.
Upvotes: 2
Reputation: 977
This is how I do it. NOTE: I haven't written an actual custom control in a "library", I usually just use "promoted widgets".
Header File:
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QObject>
#include <QWidget>
class MyWidget: public QWidget
{
Q_OBJECT
Q_PROPERTY(int value READ value WRITE setValue)
private:
int m_value;
public:
MyWidget(QWidget *parent=0);
inline int value() const {return m_value;}
void setValue(int value);
signals:
void valueChanged();
};
#endif // MYWIDGET_H
Source File:
#include "MyWidget.h"
MyWidget::MyWidget(QWidget *parent)
:QWidget(parent)
{
m_value = 0;
}
void MyWidget::setValue(int value)
{
if (m_value == value) return;
m_value = value;
emit valueChanged();
update(); // This will cause repaint
}
Upvotes: 2
Reputation: 5137
You can simply call update()
in the setter. If you want to only accept limited range of values, you can limit that in a setter or use an enum instead of an int.
#include <QLabel>
class LabelHeader : public QLabel
{
Q_OBJECT
public:
Q_PROPERTY(Pattern pattern READ(getPattern) WRITE(setPattern))
enum Pattern { FIRST = 0, SECOND, THIRD };
Q_ENUM(Pattern)
...
void setPattern(Pattern value)
{
if (pattern != value)
{
pattern = value;
update();
}
}
Pattern getPattern() const { return pattern; }
...
private:
Pattern pattern { FIRST };
};
Upvotes: 3