liudianwu |
2016-11-06 16:48 |
Qt编写自定义控件一开关按钮
从2010年进入互联网+智能手机时代以来,各种各样的APP大行其道,手机上面的APP有很多流行的元素,开关按钮个人非常喜欢,手机QQ、360卫士、金山毒霸等,都有很多开关控制一些操作,在Qt widgets应用项目上,在项目中应用些类似的开关按钮,估计也会为项目增添不少新鲜感。 总结了大部分的开关按钮控件,基本上有两大类,第一类是纯代码绘制,这种对代码的掌控度要求比较高,但是灵活性比较好。第二类是贴图,专业的美工做好的各种状态的背景图片,只需要用代码将该图片画到界面上即可。为了能够涵盖两大类的开关按钮,特意将常见的四种类型(圆角矩形/内圆形/外圆形/图片)都集成到了自定义的开关按钮中。 运行效果: [attachment=15942]
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 / 2; int pixY = rect().center().y() - targetHeight / 2; 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 = 0, //圆角矩形 ButtonStyle_CircleIn = 1, //内圆形 ButtonStyle_CircleOut = 2,//外圆形 ButtonStyle_Image = 3 //图片 };
SwitchButton(QWidget *parent = 0); ~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(225, 225, 225); bgColorOn = QColor(250, 250, 250);
sliderColorOff = QColor(100, 100, 100); sliderColorOn = QColor(100, 184, 255);
textColorOff = QColor(255, 255, 255); textColorOn = QColor(10, 10, 10);
textOff = ""; textOn = "";
imageOff = ":/image/btncheckoff1.png"; imageOn = ":/image/btncheckon1.png";
space = 2; rectRadius = 5;
step = width() / 50; startX = 0; endX = 0;
timer = new QTimer(this); timer->setInterval(5); connect(timer, SIGNAL(timeout()), this, SLOT(updateValue()));
setFont(QFont("Microsoft Yahei", 10)); }
SwitchButton::~SwitchButton() {
}
void SwitchButton::mousePressEvent(QMouseEvent *) { checked = !checked; emit checkedChanged(checked);
//每次移动的步长为宽度的 50分之一 step = width() / 50;
//状态切换改变后自动计算终点坐标 if (checked) { if (buttonStyle == ButtonStyle_Rect) { endX = width() - width() / 2; } else if (buttonStyle == ButtonStyle_CircleIn) { endX = width() - height(); } else if (buttonStyle == ButtonStyle_CircleOut) { endX = width() - height() + space; } } else { endX = 0; }
timer->start(); }
void SwitchButton::resizeEvent(QResizeEvent *) { //每次移动的步长为宽度的 50分之一 step = width() / 50;
//尺寸大小改变后自动设置起点坐标为终点 if (checked) { if (buttonStyle == ButtonStyle_Rect) { startX = width() - width() / 2; } else if (buttonStyle == ButtonStyle_CircleIn) { startX = width() - height(); } else if (buttonStyle == ButtonStyle_CircleOut) { startX = width() - height() + space; } } else { startX = 0; }
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(0, 0, width(), height()); //半径为高度的一半 int radius = rect.height() / 2; //圆的宽度为高度 int circleWidth = rect.height();
QPainterPath path; path.moveTo(radius, rect.left()); path.arcTo(QRectF(rect.left(), rect.top(), circleWidth, circleWidth), 90, 180); path.lineTo(rect.width() - radius, rect.height()); path.arcTo(QRectF(rect.width() - rect.height(), rect.top(), circleWidth, circleWidth), 270, 180); path.lineTo(radius, rect.top());
painter->drawPath(path); } else if (buttonStyle == ButtonStyle_CircleOut) { QRect rect(space, space, width() - space * 2, height() - space * 2); 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() / 2 - space * 2; int sliderHeight = height() - space * 2; QRect sliderRect(startX + space, space, sliderWidth , sliderHeight); painter->drawRoundedRect(sliderRect, rectRadius, rectRadius); } else if (buttonStyle == ButtonStyle_CircleIn) { QRect rect(0, 0, width(), height()); int sliderWidth = rect.height() - space * 2; QRect sliderRect(startX + space, space, sliderWidth, sliderWidth); painter->drawEllipse(sliderRect); } else if (buttonStyle == ButtonStyle_CircleOut) { QRect rect(0, 0, width() - space, height() - space); int sliderWidth = rect.height(); QRect sliderRect(startX, space / 2, sliderWidth, sliderWidth); painter->drawEllipse(sliderRect); }
painter->restore(); }
void SwitchButton::drawText(QPainter *painter) { painter->save();
if (!checked) { painter->setPen(textColorOff); painter->drawText(width() / 2, 0, width() / 2 - space, height(), Qt::AlignCenter, textOff); } else { painter->setPen(textColorOn); painter->drawText(0, 0, width() / 2 + space * 2, 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 / 2; int pixY = rect().center().y() - targetHeight / 2; 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程序。QQ:517216493 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图表的交互使用。 |
|