Qt Designer自定义控件创建、使用

Qt Designer自定义控件创建、使用

如何创建一个自定义的QWidget控件并导入Qt Designer 中进行使用?

一、创建Qt Designer自定义控件

第一步: 创建Qt Designer自定义控件工程

打开Qt Creator,创建一个Qt 设计师自定义控件。
Qt Designer自定义控件创建、使用_第1张图片

根据向导创建控件工程,并填写控件类名称、说明、以及docxml默认添加的属性信息
Qt Designer自定义控件创建、使用_第2张图片
Qt Designer自定义控件创建、使用_第3张图片

Qt Designer自定义控件主要是集成、实现QDesignerCustomWidgetInterface接口,在Qt Designer设计器加载ui的时候,会加载环境中这些实现了该接口的特殊图形控件。

这个工程创建后,会生成myclockplugin类,其中domXml、name、group可以根据自己的需求进行修改,默认也可以。

第二步: 实现自己的QWidget控件

然后,MyClock类才是真正实现自己定义的QWidget,可以重新绘制图形控件,也可以添加新的属性、方法等等。

这里以MyClock是参照Qt 例子中Analog Clock example做的一个钟表,主要就是在paintEvent函数中重新绘制了钟表图形,具体可以参照Analog Clock的代码。

第三步: 生成自定义控件dll并安装到Qt 工具内

编译构建自定义控件工程,会生成自定义控件的动态库文件
Qt Designer自定义控件创建、使用_第4张图片
将myclockplugin.dll安装到Qt环境中,也就是C:\Qt\Qt5.9.1\Tools\QtCreator\bin\plugins\designer路径下。
Qt Designer自定义控件创建、使用_第5张图片
重启Qt Creator工程后,打开Qt Designer工具就能在左侧列表中找到自定义的控件加载到设计器列表中。
Qt Designer自定义控件创建、使用_第6张图片

二、给自定义控件属性

所有集成QObject的Qt类对象,都通过Qt的元对象系统查询到它,获取对象的属性、方法、信号等等,这里想要给自定义的控件追加一个属性,并想显示到设计器的列表中,需要给控件类追加Q_PROPERTY属性,具体如下:

class QDESIGNER_WIDGET_EXPORT MyClock : public QWidget
{
    Q_OBJECT
    Q_ENUMS(InputMode)
    Q_PROPERTY(InputMode inputMode READ inputMode WRITE setInputMode
public:
    MyClock(QWidget *parent = 0);
    enum InputMode{
        ZONE_0 = 0,      //float number mode
        ZONE_1,
        ZONE_2//Degree second minute mode
    };
    InputMode inputMode()const;
    void setInputMode(const InputMode mode);
public slots:
    void setTimeZone(int hourOffset);
signals:
    void updated(QTime currentTime);
protected:
    void paintEvent(QPaintEvent *event) override;
private:
    int timeZoneOffset;
    InputMode m_Mode;
};
MyClock::MyClock(QWidget *parent) :
    QWidget(parent)
    ,timeZoneOffset(0)
    ,m_Mode(ZONE_0)
{
    //! [3] //! [4]
    QTimer *timer = new QTimer(this);
    //! [4] //! [5]
    connect(timer, SIGNAL(timeout()), this, SLOT(update()));
    //! [5] //! [6]
    timer->start(1000);
    //! [6]

    setWindowTitle(tr("Analog Clock"));
    resize(400, 400);
    //! [7]
}
void MyClock::paintEvent(QPaintEvent *)
//! [8] //! [10]
{
    static const QPoint hourHand[3] = {
        QPoint(7, 8),
        QPoint(-7, 8),
        QPoint(0, -40)
    };
    static const QPoint minuteHand[3] = {
        QPoint(7, 8),
        QPoint(-7, 8),
        QPoint(0, -70)
    };

    QColor hourColor(127, 0, 127);
    QColor minuteColor(0, 127, 127, 191);

    int side = qMin(width(), height());
    QTime time = QTime::currentTime();
    time = time.addSecs(timeZoneOffset);
//! [10]

//! [11]
    QPainter painter(this);
//! [11] //! [12]
    painter.setRenderHint(QPainter::Antialiasing);
//! [12] //! [13]
    painter.translate(width() / 2, height() / 2);
//! [13] //! [14]
    painter.scale(side / 200.0, side / 200.0);
//! [9] //! [14]

//! [15]
    painter.setPen(Qt::NoPen);
//! [15] //! [16]
    painter.setBrush(hourColor);
//! [16]

//! [17] //! [18]
    painter.save();
//! [17] //! [19]
    painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0)));
    painter.drawConvexPolygon(hourHand, 3);
    painter.restore();
//! [18] //! [19]

//! [20]
    painter.setPen(hourColor);
//! [20] //! [21]

    for (int i = 0; i < 12; ++i) {
        painter.drawLine(88, 0, 96, 0);
        painter.rotate(30.0);
    }
//! [21]

//! [22]
    painter.setPen(Qt::NoPen);
//! [22] //! [23]
    painter.setBrush(minuteColor);

//! [24]
    painter.save();
    painter.rotate(6.0 * (time.minute() + time.second() / 60.0));
    painter.drawConvexPolygon(minuteHand, 3);
    painter.restore();
//! [23] //! [24]

//! [25]
    painter.setPen(minuteColor);
//! [25] //! [26]

//! [27]
    for (int j = 0; j < 60; ++j) {
        if ((j % 5) != 0)
            painter.drawLine(92, 0, 96, 0);
        painter.rotate(6.0);
    }
//! [27]
}
void MyClock::setTimeZone(int hourOffset)
{
    setInputMode(InputMode(hourOffset));
}
MyClock::InputMode MyClock::inputMode() const
{
    return m_Mode;
}
void MyClock::setInputMode(const InputMode mode)
{
    timeZoneOffset = qMin(qMax(-12, int(mode)), 12) * 3600;
    update();
}

Q_PROPERTY 追加一个修改时区的属性值,编译完成后,安装到Qt Tool中,重启就可以在设计器中修改该属性。

三、在工程中使用自定义控件

创建一个工程,把MyClock添加到自己的ui中,注意需要把MyClock插件的lib、头文件引到工程内,方便运行调试
Qt Designer自定义控件创建、使用_第7张图片
inputMode也在右侧属性列表中,可以在设计器里直接设置属性值
Qt Designer自定义控件创建、使用_第8张图片
在声明MyClock类的时候,追加了QDESIGNER_WIDGET_EXPORT,这样能够保证MyClock类内的信号、槽函数等能够正确地被Qt Designer进入进去,比如:

public slots:
    void setTimeZone(int hourOffset);
signals:
    void updated(QTime currentTime);

setTimeZone和updated就可以在设计器中操作信号、操处理。
在这里插入图片描述
运行demo,当更改时区后,钟表和timeEdit也跟着更新,这就是通过设计器内绑定的信号槽关系处理的,这些都不需要再在demo工程中去重新代码来实现了。
Qt Designer自定义控件创建、使用_第9张图片

你可能感兴趣的:(QT,学习)