当前位置: 首页 > article >正文

Qt自定义 Widget 组件

自定义 Widget 子类 QmyBattery

Qt 的 UI 设计器提供了很多 GUI 设计的界面组件,可以满足常见的界面设计需求。但是某些时候需要设计一些特殊的界面组件,而在 UI 设计器的组件面板里根本没有合适的组件,这时就需要设计自定义的界面组件。
所有界面组件的基类是 QWidget,要设计自定义的界面组件,可以从 QWidget 继承一个自定义的类,重定义其 paintEvent() 事件,利用 Qt 的绘图功能绘制组件外观,并实现需要的其他功能。
例如,假设需要设计一个如图所示的电池电量显示组件,用于电池使用或充电时显示电量,但是在 UI 设计器的组件面板没有现成的组件。这就需要设计一个自定义的 Widget 组件。

image.png

为此,设计一个从 QWidget 继承的类 QmyBattery。创建 C++类,可以单击 Qt Creator 的“File”->“New File or Project”菜单选项,在出现的对话框选择 C++组里面的 C++Class,在向导中设置类的名称,并选择基类为 QWidget。定义 QmyBattery 类的头文件如下:

#include    <QWidget>
#include    <QColor>

class QmyBattery : public QWidget
{
    Q_OBJECT
//自定义属性
    Q_PROPERTY(int  powerLevel READ powerLevel WRITE setPowerLevel NOTIFY powerLevelChanged)

private:
    QColor  mColorBack=Qt::white;//背景颜色
    QColor  mColorBorder=Qt::black;//电池边框颜色
    QColor  mColorPower=Qt::green;//电量柱颜色
    QColor  mColorWarning=Qt::red;//电量短缺时的颜色

    int mPowerLevel=60;//电量0-100
    int mWarnLevel=20;//电量低警示阈值

protected:
    void    paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;

public:
    explicit QmyBattery(QWidget *parent = 0);

    void    setPowerLevel(int pow);//设置当前电量
    int     powerLevel();

    void    setWarnLevel(int warn);//设置电量低阈值
    int     warnLevel();

    QSize   sizeHint();//报告缺省大小

signals:
    void   powerLevelChanged(int );

public slots:
};

在 private 部分定义了几个私有变量,主要是各种颜色的定义,当前电量值 mPowerLevel 和电量低阈值 mWarnLevel;protected 部分重定义了 patinEvent() 事件;public 部分定义了用来读取和设置当前电量值、电量低阈值的好函数,还定义了 sizeHint() 函数,用于返回组件缺省大小。
定义了一个信号 powerLevelChanged(int),在当前电量值改变的时候发射该信号,使用 QmyBattery 类时可以设计槽函数对此信号做处理。下面是具体的实现代码,复杂的部分是 paintEvent() 事件函数里绘制界面功能实现,这里设置了窗口逻辑坐标,所以当组件大小变化时,绘制的电池大小也会自动变化。

void QmyBattery::paintEvent(QPaintEvent *event)
{  //界面组件的绘制
    Q_UNUSED(event);

    QPainter    painter(this);
    QRect rect(0,0,width(),height()); //viewport矩形区
    painter.setViewport(rect);//设置Viewport
    painter.setWindow(0,0,120,50); // 设置窗口大小,逻辑坐标
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setRenderHint(QPainter::TextAntialiasing);


//绘制电池边框
    QPen    pen;//设置画笔
    pen.setWidth(2); //线宽
    pen.setColor(mColorBorder); //划线颜色
    pen.setStyle(Qt::SolidLine);//线的类型,实线、虚线等
    pen.setCapStyle(Qt::FlatCap);//线端点样式
    pen.setJoinStyle(Qt::BevelJoin);//线的连接点样式
    painter.setPen(pen);

    QBrush  brush;//设置画刷
    brush.setColor(mColorBack); //画刷颜色
    brush.setStyle(Qt::SolidPattern); //画刷填充样式
    painter.setBrush(brush);

    rect.setRect(1,1,109,48);
    painter.drawRect(rect);//绘制电池边框

    brush.setColor(mColorBorder); //画刷颜色
    painter.setBrush(brush);
    rect.setRect(110,15,10,20);
    painter.drawRect(rect); //画电池正极头

//画电池柱
    if (mPowerLevel>mWarnLevel)
    {  //正常颜色电量柱
        brush.setColor(mColorPower); //画刷颜色
        pen.setColor(mColorPower); //划线颜色
    }
    else
    { //电量低电量柱
        brush.setColor(mColorWarning); //画刷颜色
        pen.setColor(mColorWarning); //划线颜色
    }
    painter.setBrush(brush);
    painter.setPen(pen);

    if (mPowerLevel>0)
    {
        rect.setRect(5,5,mPowerLevel,40);
        painter.drawRect(rect);//画电池柱
    }

//绘制电量百分比文字
    QFontMetrics    textSize(this->font());
    QString powStr=QString::asprintf("%d%%",mPowerLevel);
    QRect textRect=textSize.boundingRect(powStr);//得到字符串的rect

    painter.setFont(this->font());
    pen.setColor(mColorBorder); //划线颜色
    painter.setPen(pen);

    painter.drawText(55-textRect.width()/2,
               23+textRect.height()/2,
               powStr);
}

QmyBattery::QmyBattery(QWidget *parent) : QWidget(parent)
{
//    setPalette(QPalette(mColorBack));
//    setAutoFillBackground(true);
//    this->resize(120,50);
}

void QmyBattery::setPowerLevel(int pow)
{ //设置当前电量值
    mPowerLevel=pow;
    emit powerLevelChanged(pow); //触发信号
    repaint();
}

int QmyBattery::powerLevel()
{ //读取当前电量值
    return mPowerLevel;
}

void QmyBattery::setWarnLevel(int warn)
{//设置电量低阈值
    mWarnLevel=warn;
    repaint();
}

int QmyBattery::warnLevel()
{//读取电量低阈值
    return  mWarnLevel;
}

QSize QmyBattery::sizeHint()
{//报告缺省大小,调整比例
    int H=this->height();
    int W=H*12/5;
    QSize   size(W,H);
    return size;
}

自定义 Widget 组件的使用

实现了自定义类后,如果是使用代码创建 QmyBattery 类对象,其使用与一般的组件类是一样的;如果是在 UI 设计器中使用 QmyBattery,则需要采用提升的方法(promotion)。
拖一个 QWidget 组件在窗口上,右击选择“提升为(Promote to)“,就会出现如下所示对话框:

image.png

在基类名称的下来列表里选择 QWidget,将提升后的类名设置为 QmyBattery,头文件名会自动生成。可以将设置添加到已提升的列表里,以便重复使用。在提供组件之后,虽然 QWidget 已经被提升为 QmyBattery 类,但是在这个组件的“Go to slot”对话框没有 QmyBattery 类的 powerLevelChanged(int) 信号,无法采用可视化方法生成信号的槽函数。在主窗口上放置一个 QSlider 组件和一个 QLabel 组件。华东标尺改变数据时,设置为 battery 的当前电量,其 valueChanged()信号的槽函数代码如下:

void Widget::on_horizontalSlider_valueChanged(int value)
{
   ui->battery->setPowerLevel(value);
   QString  str=QStringLiteral("当前电量:")+QString::asprintf("%d %%",value);
   ui->LabInfo->setText(str);
}

下一篇文章说说如何创建 Qt Designer 的插件,可以直接在 UI 设计器中拖动使用。
参考资料:https://github.com/0voice


http://www.kler.cn/a/421834.html

相关文章:

  • Leetcode热题100-287 寻找重复数
  • lua-cjson 例子
  • 批量生成不同用户的pdf 文件(html样式)
  • 【C++进阶篇】C++继承进阶:深入理解继承的复杂性
  • 基础入门-Web应用OSS存储负载均衡CDN加速反向代理WAF防护部署影响
  • Recaptcha2 图像识别 API 对接说明
  • flask的第一个应用
  • 设计模式——方法链or流式接口
  • 什么是 Kubernetes(K8s)?
  • Chapter 17 v-model进阶
  • 深入探讨锁升级问题
  • 基于Java Springboot智慧农业微信小程序
  • 0.Git初步概念
  • 【Linux】设计文件系统(C实现)
  • 【C#】书籍信息的添加、修改、查询、删除
  • C++创建动态链接库(附原因说明)
  • 20241129解决在Ubuntu20.04下编译中科创达的CM6125的Android10出现找不到库文件libncurses.so.5的问题
  • Neo4j APOC-01-图数据库 apoc 插件 windows10 安装
  • web移动端、pc端获取浏览器指纹-fingerprintjs插件(类似mac地址)
  • HDFS怎么查看文件存储位置?