简体   繁体   English

如何在Qt C ++中为自定义控件添加属性?

[英]How to add property to custom control in Qt C++?

How do I properly add a property to a custom control, which when changed triggers the paint event? 如何正确地将属性添加到自定义控件,更改时会触发paint事件? The property only accepts an integer value of 0, 1 or 2. 该属性仅接受0,1或2的整数值。

The setter of the property would be called setPattern , so an example use would be setPattern(0) . 属性的setter将被称为setPattern ,因此使用示例将是setPattern(0)

This property value will eventually be used to control the pattern drawn in the paint event. 此属性值最终将用于控制在paint事件中绘制的模式。

labelheader.h 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 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);
}

You can simply call update() in the setter. 您只需在setter中调用update()即可。 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. 如果您只想接受有限范围的值,可以在setter中限制它或使用枚举而不是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 };
};

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
}

Solution

To accomplish what you need you do not actually need QProperty , but a private attribute of your LabelHeader class. 要实现您的需要,您实际上并不需要QProperty ,而是LabelHeader类的私有属性 Here is a step-by-step guide, covering all your requirements: 以下是分步指南,涵盖您的所有要求:

  1. Create the enumeration type 创建枚举类型

In LabelHeader.h add: LabelHeader.h中添加:

enum PatternType {
    PatternOne = 0,
    PatternTwo,
    PatternThree
};
  1. Declare a private attribute to hold the current pattern 声明私有属性以保存当前模式

In LabelHeader.h add: LabelHeader.h中添加:

private:
    PatternType m_pattern;
  1. Right click m_pattern and select Refactor->Create Getter and Setter Member Functions 右键单击m_pattern并选择Refactor-> Create Getter和Setter Member Functions
  2. In the implementation of the setter invoke a paintEvent by calling update() , but only if the new pattern is different than the current one: 在setter的实现中,通过调用update()来调用paintEvent ,但paintEvent是新模式与当前模式不同:

     if (m_pattern == pattern) return; m_pattern = pattern; update(); 
  3. In the constructor add m_pattern to the initializer list to set its value by default 在构造函数中,将m_pattern添加到初始化列表中以默认设置其值

  4. Use the value in the LabelHeader::paintEvent to draw the corresponding pattern 使用LabelHeader::paintEvent的值绘制相应的模式

     // 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); } 

Example

I have extended the example from this answer to cover your current requirements as well. 我已经从这个答案扩展了示例,以满足您当前的要求。 The full code is available on GitHub . 完整代码可在GitHub上获得

Remarks 备注

Regarding the use of Q_PROPERTY , here is an important explanation kindly provided by @KubaOber: 关于Q_PROPERTY的使用,这是@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. Q_PROPERTY是一个Qt惯用语,用于向人类读者传达意义,并将属性暴露给元类型系统,使其易于从QML等编写脚本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM