一、前言

这个控件一开始打算用样式表来实现,经过初步的探索,后面发现还是不够智能以及不能完全满足需求,比如要在此控件设置多个角标,这个用QSS就很难实现,后面才慢慢研究用QPainter来绘制,我记得当时接到这个定制控件任务的时候是2016年,那时候对QPainter的使用还不是很熟悉,也就是从此控件开始,逐步研究QPainter的绘制,把所有的内置函数都使用一遍,最终用的越来越熟悉,使得后来到了心中有坐标,万物皆painter的境界,可能就像武林中所说的打通了任督二脉吧。

本控件除了可以设置常规的圆角角度,边框宽度,边框颜色,正常颜色,按下颜色以外,还可以设置各个角标和正文文字内容/字体/对齐方式/颜色,同时还要提供三种颜色展示模式,松开按下两种颜色,按下松开颜色上下交替,按下松开颜色渐变交替。QLinearGradient是个好东西,各种颜色交替效果全靠它来实现。

二、实现的功能

  • 1:可设置圆角角度,边框宽度
  • 2:可设置角标和正文文字内容/字体/对齐方式/颜色
  • 3:可设置边框颜色,正常颜色,按下颜色
  • 4:可设置背景图片
  • 5:可设置按钮颜色模式

三、效果图

四、头文件代码

  1. #ifndef COLORBUTTON_H
  2. #define COLORBUTTON_H
  3. /**
  4. * 多样式超级按钮控件 作者:feiyangqingyun(QQ:517216493) 2017-9-24
  5. * 1:可设置圆角角度,边框宽度
  6. * 2:可设置角标和正文文字内容/字体/对齐方式/颜色
  7. * 3:可设置边框颜色,正常颜色,按下颜色
  8. * 4:可设置背景图片
  9. * 5:可设置按钮颜色模式
  10. */
  11. #include <QWidget>
  12. #ifdef quc
  13. #if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
  14. #include <QtDesigner/QDesignerExportWidget>
  15. #else
  16. #include <QtUiPlugin/QDesignerExportWidget>
  17. #endif
  18. class QDESIGNER_WIDGET_EXPORT ColorButton : public QWidget
  19. #else
  20. class ColorButton : public QWidget
  21. #endif
  22. {
  23. Q_OBJECT
  24. Q_ENUMS(ColorMode)
  25. Q_ENUMS(TextAlign)
  26. Q_PROPERTY(int borderRadius READ getBorderRadius WRITE setBorderRadius)
  27. Q_PROPERTY(int borderWidth READ getBorderWidth WRITE setBorderWidth)
  28. Q_PROPERTY(QColor borderColor READ getBorderColor WRITE setBorderColor)
  29. Q_PROPERTY(bool showSuperText READ getShowSuperText WRITE setShowSuperText)
  30. Q_PROPERTY(QString superText READ getSuperText WRITE setSuperText)
  31. Q_PROPERTY(QFont superTextFont READ getSuperTextFont WRITE setSuperTextFont)
  32. Q_PROPERTY(TextAlign superTextAlign READ getSuperTextAlign WRITE setSuperTextAlign)
  33. Q_PROPERTY(QColor superTextColor READ getSuperTextColor WRITE setSuperTextColor)
  34. Q_PROPERTY(QString text READ getText WRITE setText)
  35. Q_PROPERTY(QFont textFont READ getTextFont WRITE setTextFont)
  36. Q_PROPERTY(TextAlign textAlign READ getTextAlign WRITE setTextAlign)
  37. Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor)
  38. Q_PROPERTY(QColor normalColor READ getNormalColor WRITE setNormalColor)
  39. Q_PROPERTY(QColor pressedColor READ getPressedColor WRITE setPressedColor)
  40. Q_PROPERTY(bool canMove READ getCanMove WRITE setCanMove)
  41. Q_PROPERTY(QPixmap bgImage READ getBgImage WRITE setBgImage)
  42. Q_PROPERTY(ColorMode colorMode READ getColorMode WRITE setColorMode)
  43. public:
  44. enum ColorMode {
  45. ColorMode_Normal = 0, //松开按下两种颜色
  46. ColorMode_Replace = 1, //按下松开颜色上下交替
  47. ColorMode_Shade = 2 //按下松开颜色渐变交替
  48. };
  49. enum TextAlign {
  50. TextAlign_Top_Left = 0,
  51. TextAlign_Top_Center = 1,
  52. TextAlign_Top_Right = 2,
  53. TextAlign_Center_Left = 3,
  54. TextAlign_Center_Center = 4,
  55. TextAlign_Center_Right = 5,
  56. TextAlign_Bottom_Left = 6,
  57. TextAlign_Bottom_Center = 7,
  58. TextAlign_Bottom_Right = 8
  59. };
  60. explicit ColorButton(QWidget *parent = 0);
  61. protected:
  62. void mousePressEvent(QMouseEvent *);
  63. protected:
  64. bool eventFilter(QObject *watched, QEvent *event);
  65. void paintEvent(QPaintEvent *);
  66. void drawBg(QPainter *painter);
  67. void drawText(QPainter *painter);
  68. private:
  69. int borderRadius; //圆角半径
  70. int borderWidth; //边框宽度
  71. QColor borderColor; //边框颜色
  72. bool showSuperText; //显示角标
  73. QString superText; //角标文字
  74. QFont superTextFont; //角标文字字体
  75. TextAlign superTextAlign; //角标文字对齐方式
  76. QColor superTextColor; //角标文字颜色
  77. QString text; //文字
  78. QFont textFont; //文字字体
  79. TextAlign textAlign; //文字对齐方式
  80. QColor textColor; //文字颜色
  81. QColor normalColor; //正常颜色
  82. QColor pressedColor; //按下颜色
  83. bool canMove; //是否能移动
  84. QPixmap bgImage; //背景图片
  85. ColorMode colorMode; //背景色模式
  86. bool isPressed; //是否按下
  87. public:
  88. int getBorderRadius() const;
  89. int getBorderWidth() const;
  90. QColor getBorderColor() const;
  91. bool getShowSuperText() const;
  92. QString getSuperText() const;
  93. QFont getSuperTextFont() const;
  94. TextAlign getSuperTextAlign()const;
  95. QColor getSuperTextColor() const;
  96. QString getText() const;
  97. QFont getTextFont() const;
  98. TextAlign getTextAlign() const;
  99. QColor getTextColor() const;
  100. QColor getNormalColor() const;
  101. QColor getPressedColor() const;
  102. bool getCanMove() const;
  103. QPixmap getBgImage() const;
  104. ColorMode getColorMode() const;
  105. QSize sizeHint() const;
  106. QSize minimumSizeHint() const;
  107. public Q_SLOTS:
  108. //设置边框圆角角度
  109. void setBorderRadius(int borderRadius);
  110. //设置边框宽度
  111. void setBorderWidth(int borderWidth);
  112. //设置边框颜色
  113. void setBorderColor(const QColor &borderColor);
  114. //设置是否显示角标
  115. void setShowSuperText(bool showSuperText);
  116. //设置角标文字
  117. void setSuperText(const QString &superText);
  118. //设置角标文字字体
  119. void setSuperTextFont(const QFont &superTextFont);
  120. //设置角标文字对齐方式
  121. void setSuperTextAlign(const TextAlign &superTextAlign);
  122. //设置角标文字颜色
  123. void setSuperTextColor(const QColor &superTextColor);
  124. //设置文字
  125. void setText(const QString &text);
  126. //设置文字字体
  127. void setTextFont(const QFont &textFont);
  128. //设置文字对齐方式
  129. void setTextAlign(const TextAlign &textAlign);
  130. //设置文字颜色
  131. void setTextColor(const QColor &textColor);
  132. //设置正常颜色
  133. void setNormalColor(const QColor &normalColor);
  134. //设置按下颜色
  135. void setPressedColor(const QColor &pressedColor);
  136. //设置是否可以移动
  137. void setCanMove(bool canMove);
  138. //设置背景图片
  139. void setBgImage(const QPixmap &bgImage);
  140. //设置颜色模式
  141. void setColorMode(const ColorMode &colorMode);
  142. Q_SIGNALS:
  143. void clicked();
  144. };
  145. #endif // WKBUTTON_H

五、核心代码

  1. bool ColorButton::eventFilter(QObject *watched, QEvent *event)
  2. {
  3. if (!isEnabled()) {
  4. return QWidget::eventFilter(watched, event);
  5. }
  6. static QPoint lastPoint;
  7. if (event->type() == QEvent::MouseButtonPress) {
  8. QMouseEvent *e = static_cast<QMouseEvent *>(event);
  9. if (this->rect().contains(e->pos()) && (e->button() == Qt::LeftButton)) {
  10. lastPoint = e->pos();
  11. isPressed = true;
  12. update();
  13. }
  14. } else if (event->type() == QEvent::MouseMove && isPressed && canMove) {
  15. QMouseEvent *e = static_cast<QMouseEvent *>(event);
  16. int dx = e->pos().x() - lastPoint.x();
  17. int dy = e->pos().y() - lastPoint.y();
  18. this->move(this->x() + dx, this->y() + dy);
  19. return true;
  20. } else if (event->type() == QEvent::MouseButtonRelease && isPressed) {
  21. isPressed = false;
  22. update();
  23. }
  24. return QWidget::eventFilter(watched, event);
  25. }
  26. void ColorButton::paintEvent(QPaintEvent *)
  27. {
  28. //绘制准备工作,启用反锯齿
  29. QPainter painter(this);
  30. painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
  31. //绘制背景
  32. drawBg(&painter);
  33. //绘制文字
  34. drawText(&painter);
  35. }
  36. void ColorButton::drawBg(QPainter *painter)
  37. {
  38. painter->save();
  39. //设置边框颜色及宽度
  40. QPen pen;
  41. pen.setColor(borderColor);
  42. pen.setWidthF(borderWidth);
  43. painter->setPen(pen);
  44. //绘制区域要减去边框宽度
  45. QRect rect;
  46. rect.setX(borderWidth);
  47. rect.setY(borderWidth);
  48. rect.setWidth(width() - borderWidth * 2);
  49. rect.setHeight(height() - borderWidth * 2);
  50. //如果背景图片存在则显示背景图片,否则显示背景色
  51. if (!bgImage.isNull()) {
  52. //等比例缩放绘制
  53. QPixmap img = bgImage.scaled(rect.width(), rect.height(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
  54. painter->drawPixmap((this->rect().width() - img.width()) / 2, (this->rect().height() - img.height()) / 2, img);
  55. } else {
  56. if (colorMode == ColorMode_Normal) {
  57. if (isPressed) {
  58. painter->setBrush(QBrush(pressedColor));
  59. } else {
  60. painter->setBrush(QBrush(normalColor));
  61. }
  62. } else if (colorMode == ColorMode_Replace) {
  63. QLinearGradient gradient(QPoint(0, 0), QPoint(0, height()));
  64. if (isPressed) {
  65. gradient.setColorAt(0.0, pressedColor);
  66. gradient.setColorAt(0.49, pressedColor);
  67. gradient.setColorAt(0.50, normalColor);
  68. gradient.setColorAt(1.0, normalColor);
  69. } else {
  70. gradient.setColorAt(0.0, normalColor);
  71. gradient.setColorAt(0.49, normalColor);
  72. gradient.setColorAt(0.50, pressedColor);
  73. gradient.setColorAt(1.0, pressedColor);
  74. }
  75. painter->setBrush(gradient);
  76. } else if (colorMode == ColorMode_Shade) {
  77. QLinearGradient gradient(QPoint(0, 0), QPoint(0, height()));
  78. if (isPressed) {
  79. gradient.setColorAt(0.0, pressedColor);
  80. gradient.setColorAt(1.0, normalColor);
  81. } else {
  82. gradient.setColorAt(0.0, normalColor);
  83. gradient.setColorAt(1.0, pressedColor);
  84. }
  85. painter->setBrush(gradient);
  86. }
  87. painter->drawRoundedRect(rect, borderRadius, borderRadius);
  88. }
  89. painter->restore();
  90. }
  91. void ColorButton::drawText(QPainter *painter)
  92. {
  93. if (!bgImage.isNull()) {
  94. return;
  95. }
  96. painter->save();
  97. //如果要显示角标,则重新计算显示文字的区域
  98. if (showSuperText) {
  99. int offset = 3;
  100. QRect rect;
  101. rect.setX(borderWidth * offset);
  102. rect.setY(borderWidth);
  103. rect.setWidth(width() - borderWidth * offset * 2);
  104. rect.setHeight(height() - borderWidth * 2);
  105. Qt::Alignment alignment = Qt::AlignCenter;
  106. if (superTextAlign == TextAlign_Top_Left) {
  107. alignment = Qt::AlignTop | Qt::AlignLeft;
  108. } else if (superTextAlign == TextAlign_Top_Center) {
  109. alignment = Qt::AlignTop | Qt::AlignHCenter;
  110. } else if (superTextAlign == TextAlign_Top_Right) {
  111. alignment = Qt::AlignTop | Qt::AlignRight;
  112. } else if (superTextAlign == TextAlign_Center_Left) {
  113. alignment = Qt::AlignLeft | Qt::AlignVCenter;
  114. } else if (superTextAlign == TextAlign_Center_Center) {
  115. alignment = Qt::AlignHCenter | Qt::AlignVCenter;
  116. } else if (superTextAlign == TextAlign_Center_Right) {
  117. alignment = Qt::AlignRight | Qt::AlignVCenter;
  118. } else if (superTextAlign == TextAlign_Bottom_Left) {
  119. alignment = Qt::AlignBottom | Qt::AlignLeft;
  120. } else if (superTextAlign == TextAlign_Bottom_Center) {
  121. alignment = Qt::AlignBottom | Qt::AlignHCenter;
  122. } else if (superTextAlign == TextAlign_Bottom_Right) {
  123. alignment = Qt::AlignBottom | Qt::AlignRight;
  124. }
  125. //绘制角标
  126. painter->setPen(superTextColor);
  127. painter->setFont(superTextFont);
  128. painter->drawText(rect, alignment, superText);
  129. }
  130. int offset = 5;
  131. QRect rect;
  132. rect.setX(borderWidth * offset);
  133. rect.setY(borderWidth);
  134. rect.setWidth(width() - borderWidth * offset * 2);
  135. rect.setHeight(height() - borderWidth * 2);
  136. Qt::Alignment alignment = Qt::AlignCenter;
  137. if (textAlign == TextAlign_Top_Left) {
  138. alignment = Qt::AlignTop | Qt::AlignLeft;
  139. } else if (textAlign == TextAlign_Top_Center) {
  140. alignment = Qt::AlignTop | Qt::AlignHCenter;
  141. } else if (textAlign == TextAlign_Top_Right) {
  142. alignment = Qt::AlignTop | Qt::AlignRight;
  143. } else if (textAlign == TextAlign_Center_Left) {
  144. alignment = Qt::AlignLeft | Qt::AlignVCenter;
  145. } else if (textAlign == TextAlign_Center_Center) {
  146. alignment = Qt::AlignHCenter | Qt::AlignVCenter;
  147. } else if (textAlign == TextAlign_Center_Right) {
  148. alignment = Qt::AlignRight | Qt::AlignVCenter;
  149. } else if (textAlign == TextAlign_Bottom_Left) {
  150. alignment = Qt::AlignBottom | Qt::AlignLeft;
  151. } else if (textAlign == TextAlign_Bottom_Center) {
  152. alignment = Qt::AlignBottom | Qt::AlignHCenter;
  153. } else if (textAlign == TextAlign_Bottom_Right) {
  154. alignment = Qt::AlignBottom | Qt::AlignRight;
  155. }
  156. painter->setPen(textColor);
  157. painter->setFont(textFont);
  158. painter->drawText(rect, alignment, text);
  159. painter->restore();
  160. }

六、控件介绍

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

七、SDK下载

  • SDK下载链接:https://pan.baidu.com/s/1A5Gd77kExm8Co5ckT51vvQ 提取码:877p
  • 下载链接中包含了各个版本的动态库文件,所有控件的头文件,使用demo,自定义控件+属性设计器。
  • 自定义控件插件开放动态库dll使用(永久免费),无任何后门和限制,请放心使用。
  • 目前已提供26个版本的dll,其中包括了qt5.12.3 msvc2017 32+64 mingw 32+64 的。
  • 不定期增加控件和完善控件,不定期更新SDK,欢迎各位提出建议,谢谢!
  • widget版本(QQ:517216493)qml版本(QQ:373955953)三峰驼(QQ:278969898)。
  • 涛哥的知乎专栏 Qt进阶之路 https://zhuanlan.zhihu.com/TaoQt
  • 欢迎关注微信公众号【高效程序员】,C++/Python、学习方法、写作技巧、热门技术、职场发展等内容,干货多多,福利多多!

Qt编写自定义控件30-颜色多态按钮的更多相关文章

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

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

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

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

  3. Qt编写自定义控件38-高亮按钮

    一.前言 高亮按钮控件,既可以作为类似于交通指示灯使用,也可以作为设备状态指示灯使用,控件内置多套颜色风格,还可以自己设置颜色风格,按钮可以增加文字显示,非常适合需要在状态设备上显示小量的文字展示,按 ...

  4. Qt编写自定义控件27-颜色按钮面板

    一.前言 颜色按钮面板主要用在提供一个颜色按钮面板,用户单击某个按钮,然后拿到对应的颜色值,用户可以预先设定常用的颜色集合,传入到控件中,自动生成面板颜色集合按钮,每当滑过按钮的时候,按钮边缘高亮提示 ...

  5. Qt编写自定义控件9-导航按钮控件

    前言 导航按钮控件,主要用于各种漂亮精美的导航条,我们经常在web中看到导航条都非常精美,都是html+css+js实现的,还自带动画过度效果,Qt提供的qss其实也是无敌的,支持基本上所有的CSS2 ...

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

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

  7. Qt编写自定义控件42-开关按钮

    一.前言 从2010年进入互联网+智能手机时代以来,各种各样的APP大行其道,手机上面的APP有很多流行的元素,开关按钮个人非常喜欢,手机QQ.360卫士.金山毒霸等,都有很多开关控制一些操作,在Qt ...

  8. Qt编写自定义控件37-发光按钮(会呼吸的痛)

    一.前言 这个控件是好早以前写的,已经授权过好几个人开源过此控件代码,比如红磨坊小胖,此控件并不是来源于真实需求,而仅仅是突发奇想,类似于星星的闪烁,越到边缘越来越淡,定时器动态改变边缘发光的亮度,产 ...

  9. Qt编写自定义控件10-云台仪表盘

    前言 做过安防视频监控的同学都清楚,在视频监控系统软件上都可以看到一个云台控制区域,可以对球机进行下下左右等八个方位的运动控制,还可以进行复位,一般都是美工作图好,然后贴图的形式加入到软件中,好处是程 ...

随机推荐

  1. Unknown initial character set index '255' received from server. Initial client character 解决方法

    Unknown initial character set index '255' received from server. Initial client character set can be ...

  2. api文档设计工具:RAML、Swagger

    api文档设计工具是用来描述和辅助API开发的. 一.RAML https://raml.org/ https://wenku.baidu.com/view/9523238d5ef7ba0d4b733 ...

  3. Python+request 分模块存放接口,多接口共用参数URL、headers的抽离,添加日志打印等《三》

    主要介绍内容如下: 1.分模块存放接口 2.多接口共用参数URL.headers的抽离为配置文件 3.添加日志打印 4.一个py文件运行所有所测的接口 如上介绍内容的作用: 1.分模块存放接口:方便多 ...

  4. 再论i++ ++i

    #include <stdio.h> int main(void) { char acData[5] ={'A','B','C','D','E'}; char *pcData = NULL ...

  5. scrollReveal(页面缓入效果插件)

    scrollReveal(页面缓入效果插件)实现页面滚动时动画加载元素效果 前面我去了解了元素距页面视图距离,想实现页面滚动是动画加载元素(https://www.cnblogs.com/chengh ...

  6. [Google Guava] 2.1-不可变集合

    范例 01 public static final ImmutableSet<String> COLOR_NAMES = ImmutableSet.of( 02 "red&quo ...

  7. MySQL Index 索引提示:force or use

    一.使用索引提示(Index Hint)的条件 1.Mysql优化器错误的选择了某个索引.这种情况很少发生,需要做数据库的表.索引的统计分析. 2.某个SQL语句可选择的索引非常多,这个时候优化器执行 ...

  8. 020_统计 13:30 到 14:30 所有访问 apache 服务器的请求有多少个

    统计 13:30 到 14:30 所有访问 apache 服务器的请求有多少个 #!/bin/bash#awk 使用-F 选项指定文件内容的分隔符是/或者:#条件判断$7:$8 大于等于 13:30, ...

  9. Shell 02 数据运算/条件测试

    一.整数运算工具 1.使用expr命令(运算两边必须有空格,引用变量时必须加$符号) [root@svr5 ~]# x=10    //定义变量x expr $x + 10      20       ...

  10. CF103D Time to Raid Cowavans 根号分治+离线

    题意: 给定序列 $a,m$ 次询问,每次询问给出 $t,k$. 求 $a_{t}+a_{t+k}+a_{t+2k}+.....a_{t+pk}$ 其中 $t+(p+1)k>n$ 题解: 这种跳 ...