Qt之自定义控件(开关按钮)
2016-08-09 17:03
375 查看
简述
接触过IOS系统的童鞋们应该对开关按钮很熟悉,在设置里面经常遇到,切换时候的滑动效果比较帅气。通常说的开关按钮,有两个状态:on、off。
下面,我们利用自定义控件来实现一个开关按钮。
简述
原理
源码
示例
效果
源码
更多参考
原理
重写鼠标按下事件(mousePressEvent)、释放事件(mouseReleaseEvent),用于切换开关状态。重写绘制事件(paintEvent),用于绘制开关效果。
使用QTimer,定时刷新,让开关切换时产生动画效果。
其余接口用于扩展,也可自己扩充。
源码
SwitchControl.h#ifndef SWITCH_CONTROL #define SWITCH_CONTROL #include <QWidget> #include <QTimer> class SwitchControl : public QWidget { Q_OBJECT public: explicit SwitchControl(QWidget *parent = 0); // 返回开关状态 - 打开:true 关闭:false bool isToggled() const; // 设置开关状态 void setToggle(bool checked); // 设置背景颜色 void setBackgroundColor(QColor color); // 设置选中颜色 void setCheckedColor(QColor color); // 设置不可用颜色 void setDisbaledColor(QColor color); protected: // 绘制开关 void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; // 鼠标按下事件 void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; // 鼠标释放事件 - 切换开关状态、发射toggled()信号 void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; // 大小改变事件 void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; // 缺省大小 QSize sizeHint() const Q_DECL_OVERRIDE; QSize minimumSizeHint() const Q_DECL_OVERRIDE; signals: // 状态改变时,发射信号 void toggled(bool checked); private slots: // 状态切换时,用于产生滑动效果 void onTimeout(); private: bool m_bChecked; // 是否选中 QColor m_background; // 背景颜色 QColor m_checkedColor; // 选中颜色 QColor m_disabledColor; // 不可用颜色 QColor m_thumbColor; // 拇指颜色 qreal m_radius; // 圆角 qreal m_nX; // x点坐标 qreal m_nY; // y点坐标 qint16 m_nHeight; // 高度 qint16 m_nMargin; // 外边距 QTimer m_timer; // 定时器 }; #endif // SWITCH_CONTROL
SwitchControl.cpp
#include <QPainter> #include <QMouseEvent> #include "SwitchControl.h" SwitchControl::SwitchControl(QWidget *parent) : QWidget(parent), m_nHeight(16), m_bChecked(false), m_radius(8.0), m_nMargin(3), m_checkedColor(0, 150, 136), m_thumbColor(Qt::white), m_disabledColor(190, 190, 190), m_background(Qt::black) { // 鼠标滑过光标形状 - 手型 setCursor(Qt::PointingHandCursor); // 连接信号槽 connect(&m_timer, SIGNAL(timeout()), this, SLOT(onTimeout())); } // 绘制开关 void SwitchControl::paintEvent(QPaintEvent *event) { Q_UNUSED(event); QPainter painter(this); painter.setPen(Qt::NoPen); painter.setRenderHint(QPainter::Antialiasing); QPainterPath path; QColor background; QColor thumbColor; qreal dOpacity; if (isEnabled()) { // 可用状态 if (m_bChecked) { // 打开状态 background = m_checkedColor; thumbColor = m_checkedColor; dOpacity = 0.600; } else { //关闭状态 background = m_background; thumbColor = m_thumbColor; dOpacity = 0.800; } } else { // 不可用状态 background = m_background; dOpacity = 0.260; thumbColor = m_disabledColor; } // 绘制大椭圆 painter.setBrush(background); painter.setOpacity(dOpacity); path.addRoundedRect(QRectF(m_nMargin, m_nMargin, width() - 2 * m_nMargin, height() - 2 * m_nMargin), m_radius, m_radius); painter.drawPath(path.simplified()); // 绘制小椭圆 painter.setBrush(thumbColor); painter.setOpacity(1.0); painter.drawEllipse(QRectF(m_nX - (m_nHeight / 2), m_nY - (m_nHeight / 2), height(), height())); } // 鼠标按下事件 void SwitchControl::mousePressEvent(QMouseEvent *event) { if (isEnabled()) { if (event->buttons() & Qt::LeftButton) { event->accept(); } else { event->ignore(); } } } // 鼠标释放事件 - 切换开关状态、发射toggled()信号 void SwitchControl::mouseReleaseEvent(QMouseEvent *event) { if (isEnabled()) { if ((event->type() == QMouseEvent::MouseButtonRelease) && (event->button() == Qt::LeftButton)) { event->accept(); m_bChecked = !m_bChecked; emit toggled(m_bChecked); m_timer.start(10); } else { event->ignore(); } } } // 大小改变事件 void SwitchControl::resizeEvent(QResizeEvent *event) { m_nX = m_nHeight / 2; m_nY = m_nHeight / 2; QWidget::resizeEvent(event); } // 默认大小 QSize SwitchControl::sizeHint() const { return minimumSizeHint(); } // 最小大小 QSize SwitchControl::minimumSizeHint() const { return QSize(2 * (m_nHeight + m_nMargin), m_nHeight + 2 * m_nMargin); } // 切换状态 - 滑动 void SwitchControl::onTimeout() { if (m_bChecked) { m_nX += 1; if (m_nX >= width() - m_nHeight) m_timer.stop(); } else { m_nX -= 1; if (m_nX <= m_nHeight / 2) m_timer.stop(); } update(); } // 返回开关状态 - 打开:true 关闭:false bool SwitchControl::isToggled() const { return m_bChecked; } // 设置开关状态 void SwitchControl::setToggle(bool checked) { m_bChecked = checked; m_timer.start(10); } // 设置背景颜色 void SwitchControl::setBackgroundColor(QColor color) { m_background = color; } // 设置选中颜色 void SwitchControl::setCheckedColor(QColor color) { m_checkedColor = color; } // 设置不可用颜色 void SwitchControl::setDisbaledColor(QColor color) { m_disabledColor = color; }
示例
下面,我们来实现一组开关按钮。效果
源码
为了演示,可以设置开关的样式、以及状态等效果。SwitchControl *pSwitchControl = new SwitchControl(this); SwitchControl *pGreenSwitchControl = new SwitchControl(this); SwitchControl *pDisabledSwitchControl = new SwitchControl(this); // 设置状态、样式 pGreenSwitchControl->setToggle(true); pGreenSwitchControl->setCheckedColor(QColor(0, 160, 230)); pDisabledSwitchControl->setDisabled(true); pDisabledSwitchControl->setToggle(true); // 连接信号槽 connect(pSwitchControl, SIGNAL(toggled(bool)), this, SLOT(onToggled(bool)));
实现一个简单的槽函数,当开关按钮效果变化时,就会触发,打印当前的状态。
void MainWindow::onToggled(bool bChecked) { qDebug() << "State : " << bChecked; }
更多参考
Toggle Switch in QtQt之QCheckBox
Qt之QRadioButton
相关文章推荐
- QT学习 第一章:基本对话框
- 使用Shiboken为C++和Qt库创建Python绑定
- Qt 5.6更新至RC版,最终版本近在咫尺
- Qt定时器和随机数详解
- Qt实现图片移动实例(图文教程)
- Qt for Android开发实例教程
- QModelIndex/Role/Model介紹<二>
- Qt Model/View/Delegate浅谈 - QAbstractListModel
- Qt Model/View/Delegate浅谈 - roleNames()
- QT历程(一):与CryptoJs对应的AES加密
- 基于PyQt5的快速开发框架QFramer
- OSX下安装PyQt
- ok6410开发板移植DirectFB手记
- 【笔记】给Qt内嵌一个Chrome吧
- 【算法】最短路径之A*搜索
- qt入门必备
- 在 Qt4 中使用 C++11
- Hello Word ~ v0.2.2 背单词软件发布 -- By WHYPRO
- ubuntu下opencv和qt的安装配置
- linux下opengl的安装(with qt)