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

本文详细介绍如何在QtDesigner中创建、使用自定义QWidget控件,包括实现步骤、属性定制及工程集成,助您轻松扩展QtDesigner功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

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

打开Qt Creator,创建一个Qt 设计师自定义控件。
在这里插入图片描述

根据向导创建控件工程,并填写控件类名称、说明、以及docxml默认添加的属性信息
在这里插入图片描述
在这里插入图片描述

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

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

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

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

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

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

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

二、给自定义控件属性

所有集成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、头文件引到工程内,方便运行调试
在这里插入图片描述
inputMode也在右侧属性列表中,可以在设计器里直接设置属性值
在这里插入图片描述
在声明MyClock类的时候,追加了QDESIGNER_WIDGET_EXPORT,这样能够保证MyClock类内的信号、槽函数等能够正确地被Qt Designer进入进去,比如:

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

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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值