前言

柱状温度计控件,可能是很多人练手控件之一,基本上都是垂直方向展示,底部一个水银柱,中间刻度尺,刻度尺可以在左侧右侧或者两侧都有,自适应分辨率改动,有时候为了美观效果,可能还会整个定时器来实现动画效果,开启动画效果的缺点就是CPU占用会比较高,前阵子有个好友(贾文涛-涛哥)向我推荐了一个opengl绘制的开源东西,QNanoPainter,东西是个好东西,我个人的理解是直接封装了opengl绘制的qpainter,可以使得绘制全部走GPU,这样就可以大大减轻CPU的负担,非常方便,我自己试了下,方法和绘制逻辑和qpainter有点不一样,暂时没有将所有控件改成QNanoPainter版本,以后看情况吧。

实现的功能

  • 1:可设置精确度(小数点后几位)和间距
  • 2:可设置背景色/柱状颜色/线条颜色
  • 3:可设置长线条步长及短线条步长
  • 4:可启用动画及动画步长
  • 5:可设置范围值
  • 6:支持负数刻度值
  • 7:支持任意窗体大小缩放
  • 8:可设置柱状条位置 左侧 居中 右侧
  • 9:可设置刻度尺位置 无 左侧 右侧 两侧
  • 10:可设置用户设定目标值

效果图

头文件代码

#ifndef RULERTEMP_H
#define RULERTEMP_H /**
* 柱状温度计控件 作者:feiyangqingyun(QQ:517216493) 2016-11-4
* 1:可设置精确度(小数点后几位)和间距
* 2:可设置背景色/柱状颜色/线条颜色
* 3:可设置长线条步长及短线条步长
* 4:可启用动画及动画步长
* 5:可设置范围值
* 6:支持负数刻度值
* 7:支持任意窗体大小缩放
* 8:可设置柱状条位置 左侧 居中 右侧
* 9:可设置刻度尺位置 无 左侧 右侧 两侧
* 10:可设置用户设定目标值
*/ #include <QWidget> #ifdef quc
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
#include <QtDesigner/QDesignerExportWidget>
#else
#include <QtUiPlugin/QDesignerExportWidget>
#endif class QDESIGNER_WIDGET_EXPORT RulerTemp : public QWidget
#else
class RulerTemp : public QWidget
#endif {
Q_OBJECT
Q_ENUMS(BarPosition)
Q_ENUMS(TickPosition) Q_PROPERTY(double minValue READ getMinValue WRITE setMinValue)
Q_PROPERTY(double maxValue READ getMaxValue WRITE setMaxValue)
Q_PROPERTY(double value READ getValue WRITE setValue) Q_PROPERTY(int precision READ getPrecision WRITE setPrecision)
Q_PROPERTY(int longStep READ getLongStep WRITE setLongStep)
Q_PROPERTY(int shortStep READ getShortStep WRITE setShortStep)
Q_PROPERTY(int space READ getSpace WRITE setSpace) Q_PROPERTY(bool animation READ getAnimation WRITE setAnimation)
Q_PROPERTY(double animationStep READ getAnimationStep WRITE setAnimationStep) Q_PROPERTY(bool showUserValue READ getShowUserValue WRITE setShowUserValue)
Q_PROPERTY(double userValue READ getUserValue WRITE setUserValue)
Q_PROPERTY(QColor userValueColor READ getUserValueColor WRITE setUserValueColor) Q_PROPERTY(QColor bgColorStart READ getBgColorStart WRITE setBgColorStart)
Q_PROPERTY(QColor bgColorEnd READ getBgColorEnd WRITE setBgColorEnd)
Q_PROPERTY(QColor lineColor READ getLineColor WRITE setLineColor)
Q_PROPERTY(QColor barBgColor READ getBarBgColor WRITE setBarBgColor)
Q_PROPERTY(QColor barColor READ getBarColor WRITE setBarColor) Q_PROPERTY(BarPosition barPosition READ getBarPosition WRITE setBarPosition)
Q_PROPERTY(TickPosition tickPosition READ getTickPosition WRITE setTickPosition) public:
enum BarPosition {
BarPosition_Left = 0, //左侧显示
BarPosition_Right = 1, //右侧显示
BarPosition_Center = 2 //居中显示
}; enum TickPosition {
TickPosition_Null = 0, //不显示
TickPosition_Left = 1, //左侧显示
TickPosition_Right = 2, //右侧显示
TickPosition_Both = 3 //两侧显示
}; explicit RulerTemp(QWidget *parent = 0);
~RulerTemp(); protected:
void resizeEvent(QResizeEvent *);
void paintEvent(QPaintEvent *);
void drawBg(QPainter *painter);
void drawBarBg(QPainter *painter);
void drawRuler(QPainter *painter, int type);
void drawBar(QPainter *painter);
void drawValue(QPainter *painter); private:
double minValue; //最小值
double maxValue; //最大值
double value; //目标值 int precision; //精确度,小数点后几位
int longStep; //长线条等分步长
int shortStep; //短线条等分步长
int space; //间距 bool animation; //是否启用动画显示
double animationStep; //动画显示时步长 bool showUserValue; //显示用户设定值
double userValue; //用户设定值
QColor userValueColor; //用户设定值颜色 QColor bgColorStart; //背景渐变开始颜色
QColor bgColorEnd; //背景渐变结束颜色
QColor lineColor; //线条颜色
QColor barBgColor; //柱状背景色
QColor barColor; //柱状颜色 BarPosition barPosition; //柱状条位置
TickPosition tickPosition; //刻度尺位置 int barWidth; //水银柱宽度
int barHeight; //水银柱高度
int radius; //水银柱底部圆半径
int targetX; //目标X坐标
QRectF barRect; //柱状区域
QRectF circleRect; //底部圆区域 bool reverse; //是否倒退
double currentValue; //当前值
QTimer *timer; //定时器绘制动画 private slots:
void updateValue(); public:
double getMinValue() const;
double getMaxValue() const;
double getValue() const; int getPrecision() const;
int getLongStep() const;
int getShortStep() const;
int getSpace() const; bool getAnimation() const;
double getAnimationStep() const; bool getShowUserValue() const;
double getUserValue() const;
QColor getUserValueColor() const; QColor getBgColorStart() const;
QColor getBgColorEnd() const;
QColor getLineColor() const;
QColor getBarBgColor() const;
QColor getBarColor() const; BarPosition getBarPosition() const;
TickPosition getTickPosition() const; QSize sizeHint() const;
QSize minimumSizeHint() const; public Q_SLOTS:
//设置最大最小值-范围值
void setRange(double minValue, double maxValue);
void setRange(int minValue, int maxValue); //设置最大最小值
void setMinValue(double minValue);
void setMaxValue(double maxValue); //设置目标值
void setValue(double value);
void setValue(int value); //设置精确度
void setPrecision(int precision); //设置线条等分步长
void setLongStep(int longStep);
void setShortStep(int shortStep); //设置间距
void setSpace(int space); //设置是否启用动画显示
void setAnimation(bool animation);
//设置动画显示的步长
void setAnimationStep(double animationStep); //设置是否显示用户设定值
void setShowUserValue(bool showUserValue); //设置用户值
void setUserValue(double userValue);
void setUserValue(int userValue); //设置用户设定值颜色
void setUserValueColor(const QColor &userValueColor); //设置背景颜色
void setBgColorStart(const QColor &bgColorStart);
void setBgColorEnd(const QColor &bgColorEnd); //设置线条颜色
void setLineColor(const QColor &lineColor); //设置柱状颜色
void setBarBgColor(const QColor &barBgColor);
void setBarColor(const QColor &barColor); //设置柱状条位置
void setBarPosition(const BarPosition &barPosition); //设置刻度尺位置
void setTickPosition(const TickPosition &tickPosition); Q_SIGNALS:
void valueChanged(double value);
}; #endif // RULERTEMP_H

核心代码

void RulerTemp::paintEvent(QPaintEvent *)
{
//绘制准备工作,启用反锯齿
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); //绘制背景
drawBg(&painter); //绘制标尺及刻度尺
if (tickPosition == TickPosition_Left) {
drawRuler(&painter, 0);
} else if (tickPosition == TickPosition_Right) {
drawRuler(&painter, 1);
} else if (tickPosition == TickPosition_Both) {
drawRuler(&painter, 0);
drawRuler(&painter, 1);
} //绘制水银柱背景,包含水银柱底部圆
drawBarBg(&painter); //绘制当前水银柱,包含水银柱底部圆
drawBar(&painter); //绘制当前值
drawValue(&painter);
} void RulerTemp::drawBg(QPainter *painter)
{
painter->save();
painter->setPen(Qt::NoPen);
QLinearGradient bgGradient(QPointF(0, 0), QPointF(0, height()));
bgGradient.setColorAt(0.0, bgColorStart);
bgGradient.setColorAt(1.0, bgColorEnd);
painter->setBrush(bgGradient);
painter->drawRect(rect());
painter->restore();
} void RulerTemp::drawBarBg(QPainter *painter)
{
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(barBgColor); int barX = targetX - barWidth / 2;
int barY = space;
QRectF barRect(barX, barY, barWidth, barHeight); int circleX = targetX - radius;
//偏移 2 个像素,使得看起来边缘完整
int circleY = height() - radius * 2 - 2;
int circleWidth = radius * 2;
QRectF circleRect(circleX, circleY, circleWidth, circleWidth); QPainterPath path;
path.addRect(barRect);
path.addEllipse(circleRect);
path.setFillRule(Qt::WindingFill);
painter->drawPath(path);
painter->restore();
} void RulerTemp::drawRuler(QPainter *painter, int type)
{
painter->save();
painter->setPen(lineColor); int barPercent = barWidth / 8; if (barPercent < 2) {
barPercent = 2;
} //绘制纵向标尺刻度
double length = height() - 2 * space - 2 * radius;
//计算每一格移动多少
double increment = length / (maxValue - minValue); //长线条短线条长度
int longLineLen = 10;
int shortLineLen = 7; //绘制纵向标尺线 偏移 5 像素
int offset = barWidth / 2 + 5; //左侧刻度尺需要重新计算
if (type == 0) {
offset = -offset;
longLineLen = -longLineLen;
shortLineLen = -shortLineLen;
} double initX = targetX + offset;
double initY = space + barPercent;
QPointF topPot(initX, initY);
QPointF bottomPot(initX, height() - 2 * radius - 5);
painter->drawLine(topPot, bottomPot); //根据范围值绘制刻度值及刻度值
for (int i = maxValue; i >= minValue; i = i - shortStep) {
if (i % longStep == 0) {
//绘制长线条
QPointF leftPot(initX + longLineLen, initY);
QPointF rightPot(initX, initY);
painter->drawLine(leftPot, rightPot); //绘制文字
QString strValue = QString("%1").arg((double)i, 0, 'f', precision);
double fontHeight = painter->fontMetrics().height(); if (type == 0) {
QRect textRect(initX - 45, initY - fontHeight / 3, 30, 15);
painter->drawText(textRect, Qt::AlignRight, strValue);
} else if (type == 1) {
QRect textRect(initX + longLineLen + 5, initY - fontHeight / 3, 30, 15);
painter->drawText(textRect, Qt::AlignLeft, strValue);
}
} else {
//绘制短线条
QPointF leftPot(initX + shortLineLen, initY);
QPointF rightPot(initX, initY);
painter->drawLine(leftPot, rightPot);
} initY += increment * shortStep;
} painter->restore();
} void RulerTemp::drawBar(QPainter *painter)
{
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(barColor); //计算在背景宽度的基础上缩小的百分比, 至少为 2
int barPercent = barWidth / 8;
int circlePercent = radius / 6; if (barPercent < 2) {
barPercent = 2;
} if (circlePercent < 2) {
circlePercent = 2;
} //标尺刻度高度
double length = height() - 2 * space - 2 * radius;
//计算每一格移动多少
double increment = length / (maxValue - minValue);
//计算标尺的高度
int rulerHeight = height() - 1 * space - 2 * radius; int barX = targetX - barWidth / 2;
int barY = rulerHeight - (currentValue - minValue) * increment;
barRect = QRectF(barX + barPercent, barY + barPercent, barWidth - barPercent * 2, barHeight + radius - barY); int circleX = targetX - radius;
//偏移 2 个像素,使得看起来边缘完整
int circleY = height() - radius * 2 - 2;
int circleWidth = radius * 2 - circlePercent * 2;
circleRect = QRectF(circleX + circlePercent, circleY + circlePercent, circleWidth, circleWidth); QPainterPath path;
path.addRect(barRect);
path.addEllipse(circleRect);
path.setFillRule(Qt::WindingFill);
painter->drawPath(path); //绘制用户设定值三角号
if (showUserValue) {
if (tickPosition == TickPosition_Left || tickPosition == TickPosition_Both) {
QPolygon pts;
int offset = 15;
double initX = targetX - (barWidth / 2 + 5);
double initY = rulerHeight - (userValue - minValue) * increment;
pts.append(QPoint(initX, initY));
pts.append(QPoint(initX - offset, initY - offset / 2));
pts.append(QPoint(initX - offset, initY + offset / 2));
painter->setBrush(userValueColor);
painter->drawPolygon(pts);
} if (tickPosition == TickPosition_Right || tickPosition == TickPosition_Both) {
QPolygon pts;
int offset = 15;
double initX = targetX + (barWidth / 2 + 5);
double initY = rulerHeight - (userValue - minValue) * increment;
pts.append(QPoint(initX, initY));
pts.append(QPoint(initX + offset, initY - offset / 2));
pts.append(QPoint(initX + offset, initY + offset / 2));
painter->setBrush(userValueColor);
painter->drawPolygon(pts);
}
} painter->restore();
} void RulerTemp::drawValue(QPainter *painter)
{
painter->save(); QFont font;
font.setPixelSize(circleRect.width() * 0.55);
painter->setFont(font);
painter->setPen(Qt::white);
painter->drawText(circleRect, Qt::AlignCenter, QString("%1").arg(currentValue)); painter->restore();
}

控件介绍

  1. 超过130个精美控件,涵盖了各种仪表盘、进度条、进度球、指南针、曲线图、标尺、温度计、导航条、导航栏,flatui、高亮按钮、滑动选择器、农历等。远超qwt集成的控件数量。
  2. 每个类都可以独立成一个单独的控件,零耦合,每个控件一个头文件和一个实现文件,不依赖其他文件,方便单个控件以源码形式集成到项目中,较少代码量。qwt的控件类环环相扣,高度耦合,想要使用其中一个控件,必须包含所有的代码。
  3. 全部纯Qt编写,QWidget+QPainter绘制,支持Qt4.6到Qt5.12的任何Qt版本,支持mingw、msvc、gcc等编译器,不乱码,可直接集成到Qt Creator中,和自带的控件一样使用,大部分效果只要设置几个属性即可,极为方便。
  4. 每个控件都有一个对应的单独的包含该控件源码的DEMO,方便参考使用。同时还提供一个所有控件使用的集成的DEMO。
  5. 每个控件的源代码都有详细中文注释,都按照统一设计规范编写,方便学习自定义控件的编写。
  6. 每个控件默认配色和demo对应的配色都非常精美。
  7. 超过120个可见控件,6个不可见控件。
  8. 部分控件提供多种样式风格选择,多种指示器样式选择。
  9. 所有控件自适应窗体拉伸变化。
  10. 集成自定义控件属性设计器,支持拖曳设计,所见即所得,支持导入导出xml格式。
  11. 自带activex控件demo,所有控件可以直接运行在ie浏览器中。
  12. 集成fontawesome图形字体+阿里巴巴iconfont收藏的几百个图形字体,享受图形字体带来的乐趣。
  13. 所有控件最后生成一个dll动态库文件,可以直接集成到qtcreator中拖曳设计使用。

SDK下载



Qt编写自定义控件5-柱状温度计的更多相关文章

  1. Qt编写自定义控件大全

    最新版可执行文件 http://pan.baidu.com/s/1i491FQP 不定期增加控件及修正BUG和改进算法. 总图: 1:动画按钮 * 1:可设置显示的图像和底部的文字 * 2:可设置普通 ...

  2. Qt编写自定义控件二动画按钮

    现在的web发展越来越快,很多流行的布局样式,都是从web开始的,写惯了Qt widgets 项目,很多时候想改进一下现有的人机交互,尤其是在现有的按钮上加一些动画的效果,例如鼠标移上去变大,移开还原 ...

  3. Qt编写自定义控件45-柱状标尺控件

    一.前言 这个控件写了很久了,是最早期的一批控件中的一个,和温度计控件类似,都是垂直的进度条,可以设置不同的背景颜色,左侧的刻度也可以自由设定,还提供了动画效果,其实就是开启定时器慢慢的进度到设定的目 ...

  4. Qt编写自定义控件46-树状导航栏

    一.前言 树状导航栏控件是所有控件中最牛逼最经典最厉害的一个,在很多购买者中,使用频率也是最高,因为该导航控件集合了非常多的展示效果,比如左侧图标+右侧箭头+元素前面的图标设置+各种颜色设置等,全部涵 ...

  5. Qt编写自定义控件60-声音波形图

    一.前言 这个控件源自于一个音乐播放器,在写该音乐播放器的时候,需要将音频的数据转换成对应的频谱显示,采用的fmod第三方库来处理(fmod声音系统是为游戏开发者准备的革命性音频引擎,非常强大和牛逼) ...

  6. Qt编写自定义控件59-直方动态图

    一.前言 直方动态图类似于音乐播放时候的柱状图展示,顶部提供一个横线条,当柱状上升的时候,该线条类似于帽子的形式冲到顶端,相当于柱状顶上去的感觉,给人一种动态的感觉,听音乐的同时更加赏心悦目,原理比较 ...

  7. Qt编写自定义控件58-直方对称图

    一.前言 本控件也非原创控件,是参考网上的代码而来的,对称顾名思义就是将画布平均成上下两部分,将设置的值自动按照画布高度的一半作为参照高度进行绘制,然后增加动态过渡效果,有点类似于声音播放时候的频谱效 ...

  8. Qt编写自定义控件28-颜色滑块面板

    一.前言 相比于上一个颜色按钮面板,此控件就要难很多,颜色值有三种表示形式,除了程序员最常用的RGB以外,还有HSB和CMY方式. RGB色彩模式是工业界的一种颜色标准,是通过对红(R).绿(G).蓝 ...

  9. Qt编写自定义控件25-自定义QCustomPlot

    一.前言 上次在写大屏数据可视化电子看板系统时候,提到过改造QCustomPlot来实现柱状分组图.横向柱状图.横向分组图.鼠标悬停提示等.这次单独列出来描述,有很多人疑问为啥不用QChart,或者e ...

随机推荐

  1. Kafka监控框架介绍

    前段时间在想Kafka怎么监控.怎么知道生产的消息或消费的消费是否有丢失,目前有几个开源的Kafka监控框架这里整理了下,不过这几个框架都有各自的问题侧重点不一样: 1.Kafka Monitor 2 ...

  2. Python序列函数、高级特性及高阶函数

    序列函数: enumerate: for循环时记录索引,逐个返回元组(i, item) sorted:返回新的有序列表 zip:压缩将多个序列的对应位置的元素组成元组 zip(*元组列表): 解压缩 ...

  3. angular学习笔记(2)- 前端开发环境

    angular1学习笔记(2)- 前端开发环境 1.代码编辑工具 2.断点调试工具 3.版本管理工具 4.代码合并和混淆工具 5.依赖管理工具 6.单元测试工具 7.集成测试工具 常见的前端开发工具 ...

  4. Vue 开源项目库汇总(转)

    最近做了一个Vue开源项目库汇总,里面集合了OpenDigg 上的优质的Vue开源项目库,方便移动开发人员便捷的找到自己需要的项目工具等,感兴趣的可以到GitHub上给个star.https://gi ...

  5. F - 质数检测 V2

    https://vjudge.net/contest/218366 Java解 import java.math.BigInteger; import java.util.Scanner; publi ...

  6. Redis连接出现Error: Connection reset by peer的问题是由于使用Redis的安全模式

    现在网上一查出现安全模式的连接,基本都是要关闭服务端的操作,其实这种方式是不正确的,最有效的解决方式是使用stunnel进行安全模式的连接. 我碰到的问题是微软云(其实我不想用!)连接Redis,默认 ...

  7. java文章标题及文章相似度计算hash算法实现

    参看了 https://github.com/awnuxkjy/recommend-system 对方用了 余弦 函数实现相似度计算,我则用的是 hanlp+hash 算法(Hash算法总结) 再看服 ...

  8. 【PMP】事业环境因素和组织过程资产

    事业环境因素(EEFs) 事业环境因素(EEFs):是指组织不能控制的,将对项目产生影响.限制或指令作用的各种条件. ①组织内部的事业环境因素: 组织文化.结构和治理 设施和资源的地理分布 基础设施 ...

  9. Introducing DataFrames in Apache Spark for Large Scale Data Science(中英双语)

    文章标题 Introducing DataFrames in Apache Spark for Large Scale Data Science 一个用于大规模数据科学的API——DataFrame ...

  10. Atitit 华为基本法 attilax读后感

    Atitit 华为基本法 attilax读后感 “精神对物质的比重是三比一” 认可拿破仑的这句格言 在20多年中国商业和企业史上,一个最基本.也是最大的现象就是,为什么"中国制造" ...