• 3096阅读
  • 2回复

Qt开源作品25-电池电量控件 [复制链接]

上一主题 下一主题
离线liudianwu
 

图酷模式  只看楼主 倒序阅读 楼主  发表于: 2020-06-02
## 一、前言
现在这个时代,智能手机不要太流行,满大街都是,甚至连爷爷奶奶级别的人都会用智能手机,本次要写的控件就是智能手机中的电池电量表示控件,采用纯painter绘制,其实也可以采用贴图,我估计大部分手机上的都是采用贴图的形式,贴图有个好处就是程序员不用操心,drawimage即可,速度非常快。
至于本控件没有任何技术难点,就是自动计算当前设置的电量,根据宽度的比例划分100个等分,每个等分占用多少个像素,然后电量*该比例就是要绘制的电量的区域,可以设置报警电量,低于该变量整个电池电量区域红色显示

**主要功能:**

1. 可设置开关按钮的样式 圆角矩形/内圆形/外圆形
2. 可设置选中和未选中时的背景颜色
3. 可设置选中和未选中时的滑块颜色
4. 可设置显示的文本
5. 可设置滑块离背景的间隔
6. 可设置圆角角度
7. 可设置是否显示动画过渡效果

## 二、代码思路
```c++
void Battery::paintEvent(QPaintEvent *)
{
    //绘制准备工作,启用反锯齿
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);

    //绘制边框
    drawBorder(&painter);
    //绘制背景
    drawBg(&painter);
    //绘制头部
    drawHead(&painter);
}

void Battery::drawBorder(QPainter *painter)
{
    painter->save();

    double headWidth = width() / 10;
    double batteryWidth = width() - headWidth;

    //绘制电池边框
    QPointF topLeft(5, 5);
    QPointF bottomRight(batteryWidth, height() - 5);
    batteryRect = QRectF(topLeft, bottomRight);

    painter->setPen(QPen(borderColorStart, 5));
    painter->setBrush(Qt::NoBrush);
    painter->drawRoundedRect(batteryRect, borderRadius, borderRadius);

    painter->restore();
}

void Battery::drawBg(QPainter *painter)
{
    painter->save();

    QLinearGradient batteryGradient(QPointF(0, 0), QPointF(0, height()));
    if (currentValue <= alarmValue) {
        batteryGradient.setColorAt(0.0, alarmColorStart);
        batteryGradient.setColorAt(1.0, alarmColorEnd);
    } else {
        batteryGradient.setColorAt(0.0, normalColorStart);
        batteryGradient.setColorAt(1.0, normalColorEnd);
    }

    int margin = qMin(width(), height()) / 20;
    double unit = (batteryRect.width() - (margin * 2)) / 100;
    double width = currentValue * unit;
    QPointF topLeft(batteryRect.topLeft().x() + margin, batteryRect.topLeft().y() + margin);
    QPointF bottomRight(width + margin + 5, batteryRect.bottomRight().y() - margin);
    QRectF rect(topLeft, bottomRight);

    painter->setPen(Qt::NoPen);
    painter->setBrush(batteryGradient);
    painter->drawRoundedRect(rect, bgRadius, bgRadius);

    painter->restore();
}

void Battery::drawHead(QPainter *painter)
{
    painter->save();

    QPointF headRectTopLeft(batteryRect.topRight().x(), height() / 3);
    QPointF headRectBottomRight(width(), height() - height() / 3);
    QRectF headRect(headRectTopLeft, headRectBottomRight);

    QLinearGradient headRectGradient(headRect.topLeft(), headRect.bottomLeft());
    headRectGradient.setColorAt(0.0, borderColorStart);
    headRectGradient.setColorAt(1.0, borderColorEnd);

    painter->setPen(Qt::NoPen);
    painter->setBrush(headRectGradient);
    painter->drawRoundedRect(headRect, headRadius, headRadius);

    painter->restore();
}
```

## 三、效果图



## 四、开源主页
**以上作品完整源码下载都在开源主页,会持续不断更新作品数量和质量,欢迎各位关注。**

1. 国内站点:[https://gitee.com/feiyangqingyun/QWidgetDemo](https://gitee.com/feiyangqingyun/QWidgetDemo)
2. 国际站点:[https://github.com/feiyangqingyun/QWidgetDemo](https://github.com/feiyangqingyun/QWidgetDemo)
3. 个人主页:[https://blog.csdn.net/feiyangqingyun](https://blog.csdn.net/feiyangqingyun)
4. 知乎主页:[https://www.zhihu.com/people/feiyangqingyun/](https://www.zhihu.com/people/feiyangqingyun/)
欢迎关注微信公众号:Qt实战 (各种开源作品、经验整理、项目实战技巧,专注Qt/C++软件开发,视频监控、物联网、工业控制、嵌入式软件、国产化系统应用软件开发)QQ:517216493  WX:feiyangqingyun  QQ群:751439350
在线samhuilong

只看该作者 1楼 发表于: 2020-06-02
我用typescript写的web版本电池控件的代码,来向原版致敬。

        update(): void {
            let context: CanvasRenderingContext2D = this.context;
            let width: number = this.canvasWidth;
            let height: number = this.canvasHeight;
            context.clearRect(0, 0, width, height);

            context.save();

            //绘制边框
            this.drawBorder(context);
            //绘制背景
            this.drawBg(context);
            //绘制头部
            this.drawHead(context);

            context.restore();
        }

        protected drawBorder(context: CanvasRenderingContext2D): void {
            context.save();
            let width: number = this.canvasWidth;
            let height: number = this.canvasHeight;

            let headWidth: number = width / 10;
            let batteryWidth: number = width - headWidth;

            //绘制电池边框
            let topLeft: Point = new Point(5, 5);
            let bottomRight: Point = new Point(batteryWidth, height - 5);
            this.batteryRect = new Rect(topLeft, bottomRight);

            context.strokeStyle = this.borderColorStart.name;
            context.lineWidth = 5;
            let painter = new Painter(context);

            painter.drawRoundedRect(this.batteryRect.left, this.batteryRect.top,
                this.batteryRect.width, this.batteryRect.height,
                this.borderRadius, DrawMode.Stroke);

            context.restore();
        }

        protected drawBg(context: CanvasRenderingContext2D): void {
            context.save();

            let batteryGradient: CanvasGradient = context.createLinearGradient(0, 0, 0, this.canvasHeight);
            if (this.currentValue <= this.alarmValue) {
                batteryGradient.addColorStop(0.0, this.alarmColorStart.name);
                batteryGradient.addColorStop(1.0, this.alarmColorEnd.name);
            } else {
                batteryGradient.addColorStop(0.0, this.normalColorStart.name);
                batteryGradient.addColorStop(1.0, this.normalColorEnd.name);
            }
            context.fillStyle = batteryGradient;

            let margin: number = Math.min(this.canvasWidth, this.canvasHeight) / 20;
            let unit: number = (this.batteryRect.width - (margin * 2)) / 100;
            let width: number = this.currentValue * unit;

            let topLeft: Point = new Point(this.batteryRect.left + margin, this.batteryRect.top + margin);
            let bottomRight: Point = new Point(width + margin + 5, this.batteryRect.bottom - margin);
            let rect = new Rect(topLeft, bottomRight);

            let painter = new Painter(context);
            painter.drawRoundedRect(rect.left, rect.top, rect.width, rect.height, this.bgRadius, DrawMode.Fill);

            context.restore();
        }

        protected drawHead(context: CanvasRenderingContext2D): void {
            context.save();
            let width: number = this.canvasWidth;
            let height: number = this.canvasHeight;
            let headRectTopLeft: Point = new Point(this.batteryRect.right, height / 3);
            let headRectBottomRight: Point = new Point(width, height - height / 3);
            let headRect: Rect = new Rect(headRectTopLeft, headRectBottomRight);


            let headRectGradient: CanvasGradient = context.createLinearGradient(headRect.left, headRect.top, 0, 0);
            headRectGradient.addColorStop(0.0, this.borderColorStart.name);
            headRectGradient.addColorStop(1.0, this.borderColorEnd.name);
            context.fillStyle = headRectGradient;
            let painter = new Painter(context);
            painter.drawRoundedRect(headRect.left, headRect.top, headRect.width, headRect.height, this.bgRadius, DrawMode.Fill);

            context.restore();
        }


离线liudianwu

只看该作者 2楼 发表于: 2020-06-03
回 samhuilong 的帖子
samhuilong:我用typescript写的web版本电池控件的代码,来向原版致敬。
        update(): void {
            let context: CanvasRenderingContext2D = this.context;
   .. (2020-06-02 20:30) 

龙龙牛逼!
欢迎关注微信公众号:Qt实战 (各种开源作品、经验整理、项目实战技巧,专注Qt/C++软件开发,视频监控、物联网、工业控制、嵌入式软件、国产化系统应用软件开发)QQ:517216493  WX:feiyangqingyun  QQ群:751439350
快速回复
限100 字节
 
上一个 下一个