做过安防视频监控的同学都清楚,在视频监控系统软件上都可以看到一个云台控制区域,可以对球机进行下下左右等八个方位的运动控制,还可以进行复位,一般都是美工作图好,然后贴图的形式加入到软件中,好处是程序简单,界面美工,主要取决于美工的美图能力,缺点是对于各种分辨率的适应性稍微差点,需要不同的图片切图贴图,除非默认做好的是大图自适应看不出差别,可能大部分人所在的公司都是小公司,一般美工人员比较少甚至没有,都需要程序员一人负责,甚至一开始就要考虑到各种分辨率的应用场景以及后期可能的换肤换色等。
之前做过很多自定义控件,大部分都采用了qpainter的形式绘制,有个好处就是自适应任意分辨率,所以思考着这个云台控制仪表盘也采用纯painter绘制的形式,据说纯painter绘制还可以轻松移植到qml中,这又坚定了我用qpainter绘制的决心。所谓心中有坐标系,万物皆painter。
观察云台仪表盘下来,基本上就这几部分组成,圆形底盘,八个角,中间部分按钮,整个的控件的难点就在于八个角的定位,中间部分很好定位,而且八个角不是绝对的位置,都是相对于界面的宽高按照等比例自适应排列的。八个角的鼠标按下要做出对应的反应,发送出对应型号,网上大部分人都是切图或者放置label或者按钮来贴图实现,绑定事件过滤器过滤鼠标按下然后再发出信号。我这里为了提升逼格,直接采用位置坐标计算法。

设计师designer完整源码(仅限Qt4):https://pan.baidu.com/s/1t9uKOgi7PW34Kdj7rgTlrA 
设计师designer可执行文件:https://pan.baidu.com/s/1h3oUjqBun2_YD68gry84wQ 
自定义控件Qt4封装版本:https://pan.baidu.com/s/1JnpCwIW5sY9VtViqHSCi1g 
自定义控件Qt5封装版本:https://pan.baidu.com/s/1xMGlK0PN-5yckLJI8koSmQ 
自定义控件属性设计器:https://pan.baidu.com/s/1iZvQe7L0Dfif_p50qodZ8Q

头文件代码:

#ifndef GAUGECLOUD_H
#define GAUGECLOUD_H /**
* 云台仪表盘控件 作者:feiyangqingyun(QQ:517216493) 2018-9-2
* 1:可设置背景颜色
* 2:可设置基准颜色
* 3:可设置边框颜色
* 4:可设置文本颜色
* 5:可识别每个角度+中间 鼠标按下并发出信号
* 6:可设置八个角的图标和中间图标,随便换
* 7:内置4种云台风格 黑色+白色+蓝色+紫色
* 8:支持拓展鼠标进入离开时的切换
*/ #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 GaugeCloud : public QWidget
#else
class GaugeCloud : public QWidget
#endif {
    Q_OBJECT
    Q_ENUMS(CloudStyle)     Q_PROPERTY(QColor baseColor READ getBaseColor WRITE setBaseColor)
    Q_PROPERTY(QColor bgColor READ getBgColor WRITE setBgColor)
    Q_PROPERTY(QColor arcColor READ getArcColor WRITE setArcColor)
    Q_PROPERTY(QColor borderColor READ getBorderColor WRITE setBorderColor)
    Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor)
    Q_PROPERTY(QColor pressColor READ getPressColor WRITE setPressColor)     Q_PROPERTY(QString iconText READ getIconText WRITE setIconText)
    Q_PROPERTY(QString centerText READ getCenterText WRITE setCenterText)
    Q_PROPERTY(CloudStyle cloudStyle READ getCloudStyle WRITE setCloudStyle) public:
    enum CloudStyle {
        CloudStyle_Black = 0,   //黑色风格
        CloudStyle_White = 1,   //白色风格
        CloudStyle_Blue = 2,    //蓝色风格
        CloudStyle_Purple = 3   //紫色风格
    };     explicit GaugeCloud(QWidget *parent = 0);
    ~GaugeCloud(); protected:
    void enterEvent(QEvent *);
    void leaveEvent(QEvent *);
    void mousePressEvent(QMouseEvent *);
    void mouseReleaseEvent(QMouseEvent *);
    void paintEvent(QPaintEvent *);
    void drawCircle(QPainter *painter, int radius, const QBrush &brush);
    void drawArc(QPainter *painter);
    void drawText(QPainter *painter); private:
    QColor bgColor;                 //背景颜色
    QColor baseColor;               //基准颜色
    QColor arcColor;                //圆弧颜色
    QColor borderColor;             //边框颜色
    QColor textColor;               //文字颜色
    QColor pressColor;              //按下文字颜色     QString iconText;               //八个角图标
    QString centerText;             //中间图标
    CloudStyle cloudStyle;          //云台样式     bool enter;                     //鼠标是否进入
    bool pressed;                   //鼠标是否按下
    QPoint lastPoint;               //鼠标按下处的坐标
    QRectF centerRect;              //中间区域
    QRectF leftRect;                //左侧图标区域
    QRectF topRect;                 //上侧图标区域
    QRectF rightRect;               //右侧图标区域
    QRectF bottomRect;              //下侧图标区域
    QRectF leftTopRect;             //左上角图标区域
    QRectF rightTopRect;            //右上角图标区域
    QRectF leftBottomRect;          //左下角图标区域
    QRectF rightBottomRect;         //右下角图标区域     QFont iconFont;                 //图形字体 public:
    QColor getBgColor()             const;
    QColor getBaseColor()           const;
    QColor getArcColor()            const;
    QColor getBorderColor()         const;
    QColor getTextColor()           const;
    QColor getPressColor()          const;     QString getIconText()           const;
    QString getCenterText()         const;
    CloudStyle getCloudStyle()      const;     QSize sizeHint()                const;
    QSize minimumSizeHint()         const; public Q_SLOTS:
    //设置背景颜色
    void setBgColor(const QColor &bgColor);
    //设置基准颜色
    void setBaseColor(const QColor &baseColor);
    //设置圆弧颜色
    void setArcColor(const QColor &arcColor);
    //设置边框颜色
    void setBorderColor(const QColor &borderColor);
    //设置文本颜色
    void setTextColor(const QColor &textColor);
    //设置按下文本颜色
    void setPressColor(const QColor &pressColor);     //设置八个角图标
    void setIconText(const QString &iconText);
    //设置中间图标
    void setCenterText(const QString ¢erText);
    //设置云台样式
    void setCloudStyle(const CloudStyle &cloudStyle); Q_SIGNALS:
    //鼠标按下的区域,共9个,从0-8依次表示底部/左下角/左侧/左上角/顶部/右上角/右侧/右下角/中间
    void mousePressed(int position);
}; #endif //GAUGECLOUD_H

核心代码:

void GaugeCloud::paintEvent(QPaintEvent *)
{
int width = this->width();
int height = this->height();
int side = qMin(width, height); //以中心点为基准,分别计算八方位区域和中间区域
QPointF center = this->rect().center();
double centerSize = (double)side / ((double)100 / 30);
double iconSize = (double)side / ((double)100 / 10);
double offset1 = 3.6;
double offset2 = 2.65; //中间区域
centerRect = QRectF(center.x() - centerSize / 2, center.y() - centerSize / 2, centerSize, centerSize);
//左侧图标区域
leftRect = QRectF(center.x() - iconSize * offset1, center.y() - iconSize / 2, iconSize, iconSize);
//上侧图标区域
topRect = QRectF(center.x() - iconSize / 2, center.y() - iconSize * offset1, iconSize, iconSize);
//右侧图标区域
rightRect = QRectF(center.x() + iconSize * (offset1 - 1), center.y() - iconSize / 2, iconSize, iconSize);
//下侧图标区域
bottomRect = QRectF(center.x() - iconSize / 2, center.y() + iconSize * (offset1 - 1), iconSize, iconSize);
//左上角图标区域
leftTopRect = QRectF(center.x() - iconSize * offset2, center.y() - iconSize * offset2, iconSize, iconSize);
//右上角图标区域
rightTopRect = QRectF(center.x() + iconSize * (offset2 - 1), center.y() - iconSize * offset2, iconSize, iconSize);
//左下角图标区域
leftBottomRect = QRectF(center.x() - iconSize * offset2, center.y() + iconSize * (offset2 - 1), iconSize, iconSize);
//右下角图标区域
rightBottomRect = QRectF(center.x() + iconSize * (offset2 - 1), center.y() + iconSize * (offset2 - 1), iconSize, iconSize); //绘制准备工作,启用反锯齿,平移坐标轴中心,等比例缩放
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
painter.translate(width / 2, height / 2);
painter.scale(side / 200.0, side / 200.0); if (cloudStyle == CloudStyle_Black) {
//绘制外圆背景
drawCircle(&painter, 99, bgColor);
//绘制圆弧
drawArc(&painter);
//绘制中间圆盘背景
drawCircle(&painter, 83, baseColor);
//绘制内圆背景
drawCircle(&painter, 40, arcColor);
//绘制内圆边框
drawCircle(&painter, 33, borderColor);
//绘制内圆
drawCircle(&painter, 30, (pressed && centerRect.contains(lastPoint)) ? bgColor : baseColor);
} else if (cloudStyle == CloudStyle_White) {
//绘制外圆背景
drawCircle(&painter, 99, QColor(249, 249, 249)); //设置圆锥渐变
QConicalGradient gradient(0, 0, 100);
gradient.setColorAt(0, QColor(34, 163, 169));
gradient.setColorAt(0.4, QColor(240, 201, 136));
gradient.setColorAt(0.7, QColor(211, 77, 37));
gradient.setColorAt(1, QColor(34, 163, 169)); //绘制彩色外圆
drawCircle(&painter, 90, gradient);
//绘制中间圆盘背景
drawCircle(&painter, 83, QColor(245, 245, 245));
//绘制内圆背景
drawCircle(&painter, 33, QColor(208, 208, 208));
//绘制内圆边框
drawCircle(&painter, 32, QColor(208, 208, 208));
//绘制内圆
drawCircle(&painter, 30, (pressed && centerRect.contains(lastPoint)) ? QColor(255, 255, 255) : QColor(245, 245, 245));
} else if (cloudStyle == CloudStyle_Blue) {
//设置圆锥渐变
QConicalGradient gradient(0, 0, 100);
gradient.setColorAt(0, QColor(34, 163, 169));
gradient.setColorAt(0.4, QColor(240, 201, 136));
gradient.setColorAt(0.7, QColor(211, 77, 37));
gradient.setColorAt(1, QColor(34, 163, 169)); //绘制色彩外圆
drawCircle(&painter, 99, gradient);
//绘制中间圆盘背景
drawCircle(&painter, 91, QColor(31, 66, 98));
//绘制内圆背景
drawCircle(&painter, 33, QColor(23, 54, 81));
//绘制内圆边框
drawCircle(&painter, 30, QColor(150, 150, 150));
//绘制内圆
drawCircle(&painter, 30, (pressed && centerRect.contains(lastPoint)) ? QColor(35, 82, 133) : QColor(34, 73, 115));
} else if (cloudStyle == CloudStyle_Purple) {
//设置圆锥渐变
QConicalGradient gradient(0, 0, 100);
gradient.setColorAt(0, QColor(87, 87, 155));
gradient.setColorAt(0.4, QColor(129, 82, 130));
gradient.setColorAt(0.7, QColor(54, 89, 166));
gradient.setColorAt(1, QColor(87, 87, 155)); //绘制色彩外圆
drawCircle(&painter, 99, gradient);
//绘制中间圆盘背景
drawCircle(&painter, 91, QColor(55, 55, 92));
//绘制内圆背景
drawCircle(&painter, 33, QColor(49, 48, 82));
//绘制内圆边框
drawCircle(&painter, 30, QColor(82, 78, 131));
//绘制内圆
drawCircle(&painter, 30, (pressed && centerRect.contains(lastPoint)) ? QColor(85, 81, 137) : QColor(62, 59, 103));
} //绘制八方位+中间图标
drawText(&painter); #if 0
//重置坐标系,并绘制八方位区域及中间区域,判断是否正确
painter.resetMatrix();
painter.resetTransform();
painter.setPen(Qt::white);
painter.drawRect(centerRect);
painter.drawRect(leftRect);
painter.drawRect(topRect);
painter.drawRect(rightRect);
painter.drawRect(bottomRect);
painter.drawRect(leftTopRect);
painter.drawRect(rightTopRect);
painter.drawRect(leftBottomRect);
painter.drawRect(rightBottomRect);
#endif
} void GaugeCloud::drawCircle(QPainter *painter, int radius, const QBrush &brush)
{
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(brush); //绘制圆
painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
painter->restore();
} void GaugeCloud::drawArc(QPainter *painter)
{
int radius = 91;
painter->save();
painter->setBrush(Qt::NoBrush); QPen pen;
pen.setWidthF(10);
pen.setColor(arcColor);
painter->setPen(pen); QRectF rect = QRectF(-radius, -radius, radius * 2, radius * 2);
painter->drawArc(rect, 0 * 16, 360 * 16); painter->restore();
} void GaugeCloud::drawText(QPainter *painter)
{
bool ok;
int radius = 100;
painter->save(); //判断当前按下坐标是否在中心区域,按下则文本不同颜色
if (pressed && centerRect.contains(lastPoint)) {
emit mousePressed(8);
painter->setPen(pressColor);
} else {
painter->setPen(textColor);
} QFont font;
font.setPixelSize(25);
#if (QT_VERSION >= QT_VERSION_CHECK(4,8,0))
font.setHintingPreference(QFont::PreferNoHinting);
#endif
painter->setFont(font); //绘制中间图标
QRectF centerRect(-radius, -radius, radius * 2, radius * 2);
QString centerText = this->centerText.replace("0x", "");
QChar centerChar = QChar(centerText.toInt(&ok, 16));
painter->drawText(centerRect, Qt::AlignCenter, centerChar); //绘制八方位图标
radius = 70;
int offset = 15;
int steps = 8;
double angleStep = 360.0 / steps; font.setPixelSize(20);
painter->setFont(font); //从下侧图标开始绘制,顺时针旋转
QRect iconRect(-offset / 2, radius - offset, offset, offset);
QString iconText = this->iconText.replace("0x", "");
QChar iconChar = QChar(iconText.toInt(&ok, 16));
for (int i = 0; i < steps; i++) {
//判断鼠标按下的是哪个区域
if (pressed) {
bool contains = false;
if (bottomRect.contains(lastPoint) && i == 0) {
contains = true;
} else if (leftBottomRect.contains(lastPoint) && i == 1) {
contains = true;
} else if (leftRect.contains(lastPoint) && i == 2) {
contains = true;
} else if (leftTopRect.contains(lastPoint) && i == 3) {
contains = true;
} else if (topRect.contains(lastPoint) && i == 4) {
contains = true;
} else if (rightTopRect.contains(lastPoint) && i == 5) {
contains = true;
} else if (rightRect.contains(lastPoint) && i == 6) {
contains = true;
} else if (rightBottomRect.contains(lastPoint) && i == 7) {
contains = true;
} if (contains) {
painter->setPen(pressColor);
emit mousePressed(i);
} else {
painter->setPen(textColor);
}
} else {
painter->setPen(textColor);
} painter->drawText(iconRect, Qt::AlignCenter, iconChar);
painter->rotate(angleStep);
} painter->restore();
}

 

Qt自定义控件大全(一)云台仪表盘控件的更多相关文章

  1. Qt编写自定义控件31-面板仪表盘控件

    一.前言 在Qt自定义控件中,仪表盘控件是数量最多的,写仪表盘都写到快要吐血,可能是因为各种工业控制领域用的比较多吧,而且仪表盘又是比较生动直观的,这次看到百度的echart中有这个控件,所以也来模仿 ...

  2. Qt编写自定义控件11-设备防区按钮控件

    前言 在很多项目应用中,需要根据数据动态生成对象显示在地图上,比如地图标注,同时还需要可拖动对象到指定位置显示,能有多种状态指示,安防领域一般用来表示防区或者设备,可以直接显示防区号,有多种状态颜色指 ...

  3. Qt编写自定义控件8-动画按钮组控件

    前言 动画按钮组控件可以用来当做各种漂亮的导航条用,既可以设置成顶部底部+左侧右侧,还自带精美的滑动效果,还可以设置悬停滑动等各种颜色,原创作者雨田哥(QQ:3246214072),驰骋Qt控件界多年 ...

  4. Qt编写自定义控件32-等待进度条控件

    一.前言 在各种各样的执行任务界面,有时候需要比较多的时间,需要给出一个直观的等待进度条表示当前正在执行的进度,而不至于懵逼在那里,用户不会觉得程序死了还是干嘛了. 等待进度条有好几种办法,比如直接叫 ...

  5. Qt编写自定义控件24-图片轮播控件

    一.前言 上一篇文章写的广告轮播控件,采用的传统widget堆积设置样式表做的,这次必须要用到更高级的QPainter来绘制了,这个才是最高效的办法,本控件参考雨田哥的轮播控件,经过大规模的改造而成, ...

  6. Qt编写自定义控件23-广告轮播控件

    一.前言 广告轮播这个控件做的比较早,是很早以前定制一个电信客户端时候用到的,该客户端需要在首页展示轮播预先设定好的图片,图片的路径可以自由设定,然后轮播的间隔速度可以自由控制,同时该控件还需要提供两 ...

  7. WPF自定义控件与样式(9)-树控件TreeView与菜单Menu-ContextMenu

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 菜单M ...

  8. WPF自定义控件与样式(10)-进度控件ProcessBar自定义样

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Pro ...

  9. 在Qt中使用AnyCAD三维建模控件

    AnyCAD C++ SDK专为Qt框架增加了AnyPlatformQt.lib模块,在Qt中使用AnyCAD三维建模控件变得十分简单. 下载 Qt高速下载:http://pan.baidu.com/ ...

随机推荐

  1. C#高级二

    编程小虾米大侠之梦 软件环境:win7 开发工具:vs 2010 平台:.NET 语言:C# 类库版本:.NET Framework 2.0 语言特点:强类型语言 规划知识点: 1..net fram ...

  2. Zabbix学习笔记一:基本安装与配置

    1.下载安装 http://120.52.73.43/tenet.dl.sourceforge.net/project/zabbix/ZABBIX%20Latest%20Stable/3.0.1/za ...

  3. PP生产订单的BADI增强 WORKORDER_UPDATE

    METHOD if_ex_workorder_update~before_update. *---------------------->增强1 开始* "当生产订单类型为PP01时, ...

  4. 注册表缺失导致Windows Server 2008 R2时钟服务W32time不能自启

    参照@飘云 http://blog.csdn.net/piaoyunqing/article/details/6323647 的文章. 测试环境中有一台Windows Server 2008 R2的虚 ...

  5. Angular路由——路由守卫

    一.路由守卫 当用户满足一定条件才被允许进入或者离开一个路由. 路由守卫场景: 只有当用户登录并拥有某些权限的时候才能进入某些路由. 一个由多个表单组成的向导,例如注册流程,用户只有在当前路由的组件中 ...

  6. js判断类型的四种方法

    typeof:使用typeof可以很方便的判断六种类型:undefined.boolean.string.number.object.function 数组和null会被判断为object类型 ins ...

  7. 微软、谷歌、亚马逊、Facebook等硅谷大厂91个开源软件盘点(附下载地址)

    开源软件中有大量专家构建的代码,大大节省了开发人员的时间和成本,热衷于开源的大厂们总是能够带给我们新的惊喜.2016年9月GitHub报告显示,GitHub已经有超过 520 万的用户和超 30 万的 ...

  8. 如何使用Python快速制作可视化报表----pyecharts

    如何使用Python快速制作可视化报表   数据可视化能力已经越来越成为各岗位的基础技能.领英的数据报告显示,数据可视化技能在2017年中国最热门技能中排名第一. 就数据分析而言,可视化探索几乎是你正 ...

  9. BZOJ3439 Kpm的MC密码(可持久化trie)

    将串反过来就变成查询前缀了.考虑建一棵可持久化trie,查询时二分答案,均摊一下复杂度即为O(mlogn). #include<iostream> #include<cstdio&g ...

  10. R中绘制聚类的离散图

    R中利用cluster简单的绘制常见聚类离散图 # 引入cluster库(clara.fanny) library(cluster) # 聚类散点图绘制 # 引入factoextra,cluster库 ...