从2010年进入互联网+智能手机时代以来,各种各样的APP大行其道,手机上面的APP有很多流行的元素,开关按钮个人非常喜欢,手机QQ、360卫士、金山毒霸等,都有很多开关控制一些操作,在Qt widgets应用项目上,在项目中应用些类似的开关按钮,估计也会为项目增添不少新鲜感。

总结了大部分的开关按钮控件,基本上有两大类,第一类是纯代码绘制,这种对代码的掌控度要求比较高,但是灵活性比较好。第二类是贴图,专业的美工做好的各种状态的背景图片,只需要用代码将该图片画到界面上即可。为了能够涵盖两大类的开关按钮,特意将常见的四种类型(圆角矩形/内圆形/外圆形/图片)都集成到了自定义的开关按钮中。

运行效果:

1:纯代码绘制

纯代码绘制开关按钮,可以很灵活的设置各种颜色、间隔、文字等,还可以产生动画过度的滑动效果。

产生滑动效果采用定时器绘制的方式,自动计算滑块的X轴开始坐标,当滑块的X轴开始坐标到达滑块的X轴结束坐标时停止定时器。

void SwitchButton::updateValue()
{
if (checked) {
if (startX < endX) {
startX = startX + step;
} else {
startX = endX;
timer->stop();
}
} else {
if (startX > endX) {
startX = startX - step;
} else {
startX = endX;
timer->stop();
}
}
update();
}

2:贴图绘制

void SwitchButton::drawImage(QPainter *painter)
{
painter->save();
QPixmap pix; if (!checked) {
pix = QPixmap(imageOff);
} else {
pix = QPixmap(imageOn);
} //自动等比例平滑缩放居中显示
int targetWidth = pix.width();
int targetHeight = pix.height();
pix = pix.scaled(targetWidth, targetHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); int pixX = rect().center().x() - targetWidth / ;
int pixY = rect().center().y() - targetHeight / ;
QPoint point(pixX, pixY);
painter->drawPixmap(point, pix);
painter->restore();
}

有些人说PS一张精美的图片也不是很容易,需要专业的,这里推荐一个好方法,让你也可以获取到这些图片,其实大部分的APP都可以用解压软件打开,拓展名改为.zip即可,解压出来一般里面都含有绝大部分的图片,发现绝大部分的APP都喜欢用图片作为背景来展示一些效果,而不是原原本本的用代码一点点绘制。腾讯就是腾讯啊,大公司!人家的美工MM设计的图片那真的没得话说,绝对一流,手机QQ每次升级一个版本,我都会下过来将里面的精美图片图标之类的提取出来,以便项目使用。同时还推荐两个网站:http://www.easyicon.net/ 我的所有项目用到的ico图标都是这网站上面的。http://www.ui.cn/ 专业的设计师集中营,这里面成千上万的精美的设计的图片,可以多多参考。

完整代码:

switchbutton.h

#ifndef SWITCHBUTTON_H
#define SWITCHBUTTON_H /**
* 作者:feiyangqingyun(QQ:517216493) 2016-11-6
* 1:可设置开关按钮的样式 圆角矩形/内圆形/外圆形/图片
* 2:可设置选中和未选中时的背景颜色
* 3:可设置选中和未选中时的滑块颜色
* 4:可设置显示的文本
* 5:可设置滑块离背景的间隔
* 6:可设置圆角角度
*/ #include <QWidget> class QTimer; class SwitchButton: public QWidget
{
Q_OBJECT
public:
enum ButtonStyle {
ButtonStyle_Rect = , //圆角矩形
ButtonStyle_CircleIn = , //内圆形
ButtonStyle_CircleOut = ,//外圆形
ButtonStyle_Image = //图片
}; SwitchButton(QWidget *parent = );
~SwitchButton(); protected:
void mousePressEvent(QMouseEvent *);
void resizeEvent(QResizeEvent *);
void paintEvent(QPaintEvent *);
void drawBg(QPainter *painter);
void drawSlider(QPainter *painter);
void drawText(QPainter *painter);
void drawImage(QPainter *painter); private:
bool checked; //是否选中
ButtonStyle buttonStyle; //开关按钮样式 QColor bgColorOff; //关闭时背景颜色
QColor bgColorOn; //打开时背景颜色 QColor sliderColorOff; //关闭时滑块颜色
QColor sliderColorOn; //打开时滑块颜色 QColor textColorOff; //关闭时文本颜色
QColor textColorOn; //打开时文本颜色 QString textOff; //关闭时显示的文字
QString textOn; //打开时显示的文字 QString imageOff; //关闭时显示的图片
QString imageOn; //打开时显示的图片 int space; //滑块离背景间隔
int rectRadius; //圆角角度 int step; //每次移动的步长
int startX; //滑块开始X轴坐标
int endX; //滑块结束X轴坐标
QTimer *timer; //定时器绘制 private slots:
void updateValue(); public:
bool getChecked()const
{
return checked;
}
ButtonStyle getButtonStyle()const
{
return buttonStyle;
} QColor getBgColorOff()const
{
return bgColorOff;
}
QColor getBgColorOn()const
{
return bgColorOn;
} QColor getSliderColorOff()const
{
return sliderColorOff;
}
QColor getSliderColorOn()const
{
return sliderColorOn;
} QColor getTextColorOff()const
{
return textColorOff;
}
QColor getTextColorOn()const
{
return textColorOn;
} QString getTextOff()const
{
return textOff;
}
QString getTextOn()const
{
return textOn;
} QString getImageOff()const
{
return imageOff;
}
QString getImageOn()const
{
return imageOn;
} int getSpace()const
{
return space;
}
int getRectRadius()const
{
return rectRadius;
} public slots:
//设置是否选中
void setChecked(bool checked);
//设置风格样式
void setButtonStyle(ButtonStyle buttonStyle); //设置背景颜色
void setBgColor(QColor bgColorOff, QColor bgColorOn);
//设置滑块颜色
void setSliderColor(QColor sliderColorOff, QColor sliderColorOn);
//设置文本颜色
void setTextColor(QColor textColorOff, QColor textColorOn); //设置文本
void setText(QString textOff, QString textOn); //设置背景图片
void setImage(QString imageOff, QString imageOn); //设置间隔
void setSpace(int space);
//设置圆角角度
void setRectRadius(int rectRadius); signals:
void checkedChanged(bool checked);
}; #endif // SWITCHBUTTON_H

switchbutton.cpp

#include "switchbutton.h"
#include "qpainter.h"
#include "qevent.h"
#include "qtimer.h"
#include "qdebug.h" SwitchButton::SwitchButton(QWidget *parent): QWidget(parent)
{
checked = false;
buttonStyle = ButtonStyle_Rect; bgColorOff = QColor(, , );
bgColorOn = QColor(, , ); sliderColorOff = QColor(, , );
sliderColorOn = QColor(, , ); textColorOff = QColor(, , );
textColorOn = QColor(, , ); textOff = "";
textOn = ""; imageOff = ":/image/btncheckoff1.png";
imageOn = ":/image/btncheckon1.png"; space = ;
rectRadius = ; step = width() / ;
startX = ;
endX = ; timer = new QTimer(this);
timer->setInterval();
connect(timer, SIGNAL(timeout()), this, SLOT(updateValue())); setFont(QFont("Microsoft Yahei", ));
} SwitchButton::~SwitchButton()
{ } void SwitchButton::mousePressEvent(QMouseEvent *)
{
checked = !checked;
emit checkedChanged(checked); //每次移动的步长为宽度的 50分之一
step = width() / ; //状态切换改变后自动计算终点坐标
if (checked) {
if (buttonStyle == ButtonStyle_Rect) {
endX = width() - width() / ;
} else if (buttonStyle == ButtonStyle_CircleIn) {
endX = width() - height();
} else if (buttonStyle == ButtonStyle_CircleOut) {
endX = width() - height() + space;
}
} else {
endX = ;
} timer->start();
} void SwitchButton::resizeEvent(QResizeEvent *)
{
//每次移动的步长为宽度的 50分之一
step = width() / ; //尺寸大小改变后自动设置起点坐标为终点
if (checked) {
if (buttonStyle == ButtonStyle_Rect) {
startX = width() - width() / ;
} else if (buttonStyle == ButtonStyle_CircleIn) {
startX = width() - height();
} else if (buttonStyle == ButtonStyle_CircleOut) {
startX = width() - height() + space;
}
} else {
startX = ;
} update();
} void SwitchButton::paintEvent(QPaintEvent *)
{
//绘制准备工作,启用反锯齿
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing); if (buttonStyle == ButtonStyle_Image) {
//绘制图片
drawImage(&painter);
} else {
//绘制背景
drawBg(&painter);
//绘制滑块
drawSlider(&painter);
//绘制文字
drawText(&painter);
}
} void SwitchButton::drawBg(QPainter *painter)
{
painter->save();
painter->setPen(Qt::NoPen); if (!checked) {
painter->setBrush(bgColorOff);
} else {
painter->setBrush(bgColorOn);
} if (buttonStyle == ButtonStyle_Rect) {
painter->drawRoundedRect(rect(), rectRadius, rectRadius);
} else if (buttonStyle == ButtonStyle_CircleIn) {
QRect rect(, , width(), height());
//半径为高度的一半
int radius = rect.height() / ;
//圆的宽度为高度
int circleWidth = rect.height(); QPainterPath path;
path.moveTo(radius, rect.left());
path.arcTo(QRectF(rect.left(), rect.top(), circleWidth, circleWidth), , );
path.lineTo(rect.width() - radius, rect.height());
path.arcTo(QRectF(rect.width() - rect.height(), rect.top(), circleWidth, circleWidth), , );
path.lineTo(radius, rect.top()); painter->drawPath(path);
} else if (buttonStyle == ButtonStyle_CircleOut) {
QRect rect(space, space, width() - space * , height() - space * );
painter->drawRoundedRect(rect, rectRadius, rectRadius);
} painter->restore();
} void SwitchButton::drawSlider(QPainter *painter)
{
painter->save();
painter->setPen(Qt::NoPen); if (!checked) {
painter->setBrush(sliderColorOff);
} else {
painter->setBrush(sliderColorOn);
} if (buttonStyle == ButtonStyle_Rect) {
int sliderWidth = width() / - space * ;
int sliderHeight = height() - space * ;
QRect sliderRect(startX + space, space, sliderWidth , sliderHeight);
painter->drawRoundedRect(sliderRect, rectRadius, rectRadius);
} else if (buttonStyle == ButtonStyle_CircleIn) {
QRect rect(, , width(), height());
int sliderWidth = rect.height() - space * ;
QRect sliderRect(startX + space, space, sliderWidth, sliderWidth);
painter->drawEllipse(sliderRect);
} else if (buttonStyle == ButtonStyle_CircleOut) {
QRect rect(, , width() - space, height() - space);
int sliderWidth = rect.height();
QRect sliderRect(startX, space / , sliderWidth, sliderWidth);
painter->drawEllipse(sliderRect);
} painter->restore();
} void SwitchButton::drawText(QPainter *painter)
{
painter->save(); if (!checked) {
painter->setPen(textColorOff);
painter->drawText(width() / , , width() / - space, height(), Qt::AlignCenter, textOff);
} else {
painter->setPen(textColorOn);
painter->drawText(, , width() / + space * , height(), Qt::AlignCenter, textOn);
} painter->restore();
} void SwitchButton::drawImage(QPainter *painter)
{
painter->save(); QPixmap pix; if (!checked) {
pix = QPixmap(imageOff);
} else {
pix = QPixmap(imageOn);
} //自动等比例平滑缩放居中显示
int targetWidth = pix.width();
int targetHeight = pix.height();
pix = pix.scaled(targetWidth, targetHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); int pixX = rect().center().x() - targetWidth / ;
int pixY = rect().center().y() - targetHeight / ;
QPoint point(pixX, pixY);
painter->drawPixmap(point, pix); painter->restore();
} void SwitchButton::updateValue()
{
if (checked) {
if (startX < endX) {
startX = startX + step;
} else {
startX = endX;
timer->stop();
}
} else {
if (startX > endX) {
startX = startX - step;
} else {
startX = endX;
timer->stop();
}
} update();
} void SwitchButton::setChecked(bool checked)
{
if (this->checked != checked) {
this->checked = checked;
emit checkedChanged(checked);
update();
}
} void SwitchButton::setButtonStyle(SwitchButton::ButtonStyle buttonStyle)
{
this->buttonStyle = buttonStyle;
update();
} void SwitchButton::setBgColor(QColor bgColorOff, QColor bgColorOn)
{
this->bgColorOff = bgColorOff;
this->bgColorOn = bgColorOn;
update();
} void SwitchButton::setSliderColor(QColor sliderColorOff, QColor sliderColorOn)
{
this->sliderColorOff = sliderColorOff;
this->sliderColorOn = sliderColorOn;
update();
} void SwitchButton::setTextColor(QColor textColorOff, QColor textColorOn)
{
this->textColorOff = textColorOff;
this->textColorOn = textColorOn;
update();
} void SwitchButton::setText(QString textOff, QString textOn)
{
this->textOff = textOff;
this->textOn = textOn;
update();
} void SwitchButton::setImage(QString imageOff, QString imageOn)
{
this->imageOff = imageOff;
this->imageOn = imageOn;
update();
} void SwitchButton::setSpace(int space)
{
this->space = space;
update();
} void SwitchButton::setRectRadius(int rectRadius)
{
this->rectRadius = rectRadius;
update();
}

此自定义控件集成在QFramework中。

自定义控件可执行文件下载:http://pan.baidu.com/s/1i5iCfzv

QFramework简介:

QFramework是一套通用的Qt程序开发框架,集成主界面布局、各种自定义控件、数据库处理、excel极速导出、数据打印、串口通信、网络通信、协议解析、全局热键、邮件发送,短信发送,百度地图调用、ffmpeg+vlc处理等功能,将常用的功能封装成类库,提供统一直观的调用接口,方便使用者使用,对应封装的库都有对应的demo程序。

QFramework基本功能:

1:支持从4.7.0到5.7.0的任何Qt版本,不受版本限制。用了此框架,不会再有Qt版本不同而引起的程序编译通不过的烦恼。

2:极速导出数据到excel,支持表格数据或者查询的数据,不依赖任何组件,支持任何excel、wps等表格软件版本,导出10万行数据8个字段只需要3秒完成。对导出的表格样式可自定义主标题和副标题,可对导出的数据按照指定条件红色突出显示。

3:数据导出到pdf及打印功能,支持表格数据或者查询的数据,支持横向纵向打印,自动分页。

4:数据分页dbapi类,只需传入表格对象,表名,翻页按钮即可。无需再写重复的方法处理翻页。

5:各种自定义控件,例如开关按钮、发光按钮,仪表盘控件、音量控件、温湿度控件、仪表仪器类控件等。

6:全新超级中英双拼输入法,非常适合触摸设备。

7:全局热键处理。

8:串口热敏打印机打印。

9:qcustomplot 2D图形曲线绘制(含鼠标数据跟踪)。

10:多线程邮件发送,支持多个接收邮箱。

11:多线程短信发送,支持多个接收号码及长短信。

12:Qffmpeg+Qvlc视频处理。

13:取字模,字符转LED数据处理。

14:全局日志输出类 applog,可动态挂载和卸载。

15:全局程序控制类 appkey,可控制程序的使用时间、运行时间、设备数量限制等。

16:封装百度地图调用接口,支持设备标注、路线查询、位置显示等。

17:自动清理程序早期数据类 cleanapi,传入要清理的数据库表名,执行间隔,保留的最大记录数即可。这样保证了整个系统存储的都是最新的数据。

18:NTP校时服务程序。

19:全局截图处理,可以很方便的直接在ARM上对程序进行截图。

20:程序存活检测功能 applive,通过udp通信实时发送心跳命令,这样可以保证程序7*24小时运行,在ARM上可采用 appdog看门狗程序。

21:已运行时间+当前时间+实时CPU使用率+实时内存使用率等。

22:自定义程序主界面底部信息。

23:Echart图表的交互使用。

Qt编写自定义控件一开关按钮的更多相关文章

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

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

  2. Qt编写自定义控件43-自绘电池

    一.前言 到了9102年了,现在智能手机不要太流行,满大街都是,甚至连爷爷奶奶级别的人都会用智能手机,本次要写的控件就是智能手机中的电池电量表示控件,采用纯painter绘制,其实也可以采用贴图,我估 ...

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

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

  4. Qt编写自定义控件插件开放动态库dll使用(永久免费)

    这套控件陆陆续续完善了四年多,目前共133个控件,除了十几个控件参考网友开源的代码写的,其余全部原创,在发布之初就有打算将动态库开放出来永久免费使用,在控件比较完善的今天抽了半天时间编译了多个qt版本 ...

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

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

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

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

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

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

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

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

  9. Qt编写自定义控件7-自定义可拖动多边形

    前言 自定义可拖动多边形控件,原创作者是赵彦博(QQ:408815041 zyb920@hotmail.com),创作之初主要是为了能够在视频区域内用户自定义可拖动的多个区域,即可用来作为警戒区域,也 ...

随机推荐

  1. atitit.提升开发效率---动态语言总结

    atitit.提升开发效率---动态语言总结 ruby,python 都不错,就是语法不好, 应用不广泛,文档,工具都非常少,不推荐... php狠不错,就是高级特性不行.. 看来子有.net/jav ...

  2. paip.一千 常用汉字 高频汉字 覆盖率90%

    paip.一千 常用汉字 高频汉字 覆盖率90%  一千个使用频率最高的汉字,其覆盖率达一般书刊用字的90%. 作者Attilax  艾龙,  EMAIL:1466519819@qq.com 来源:a ...

  3. iOS开发之静态库(六)—— 时空之争

    前面的所有试验中,我们的静态库都支持了所有可能的指令集(i386, x86_64, armv7, armv7s, arm64),最大限 度的匹配了所有可能运行该代码的设备,使代码在当前存在的几乎所有i ...

  4. Leetcode-283 Move Zeroes

    #283.   Move Zeroes Given an array nums, write a function to move all 0's to the end of it while mai ...

  5. c#之第一课入门

    这几天看到微软的build大会,感觉微软不甘落后他人,曾经的巨头难道又要重新崛起,不管了,为了以后的饭碗,还是简单学习一些c#吧,有时这种紧张感不错的,现在由于这种紧张感,我已经掌握的java(主要弄 ...

  6. 初识React,Virutal DOM, State以及生命周期

    这是React分类下的第一篇文章,是在了解了一些基本面后,看Tyler文章,边看边理解边写的. React可以看做是MVC中的V,关注的是视图层.React的组件就像Angular的Directive ...

  7. 【转】Android类动态加载技术

    http://www.blogjava.net/zh-weir/archive/2011/10/29/362294.html Android应用开发在一般情况下,常规的开发方式和代码架构就能满足我们的 ...

  8. Nginx开发从入门到精通 学习目录分享学习 (阿里著作)

    Nginx开发从入门到精通   缘起 nginx由于出色的性能,在世界范围内受到了越来越多人的关注,在淘宝内部它更是被广泛的使用,众多的开发以及运维同学都迫切的想要了解nginx模块的开发以及它的内部 ...

  9. fresco Bitmap too large to be uploaded into a texture

    fresco加载图片方法 布局文件引入 xmlns:fresco="http://schemas.android.com/apk/res-auto" <com.faceboo ...

  10. 记一次苦逼的SQL查询优化

    最近在维护公司项目时,需要加载某页面,总共加载也就4000多条数据,竟然需要35秒钟,要是数据增长到40000条,我估计好几分钟都搞不定.卧槽,要我是用户的话估计受不了,趁闲着没事,就想把它优化一下, ...