文档章节

qt自定义开关控件

AaronW
 AaronW
发布于 2016/08/10 15:23
字数 861
阅读 40
收藏 0
点赞 0
评论 0

简述

接触过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;
}

示例

下面,我们来实现一组开关按钮。

效果

这里写图片描述

源码

为了演示,可以设置开关的样式、以及状态等效果。

实现一个简单的槽函数,当开关按钮效果变化时,就会触发,打印当前的状态。

void MainWindow::onToggled(bool bChecked)
{
    qDebug() << "State : " << bChecked;
}

本文转载自:http://blog.csdn.net/liang19890820/article/details/52164289

共有 人打赏支持
AaronW
粉丝 2
博文 20
码字总数 5414
作品 0
杭州
程序员
《Qt 实战一二三》

简介 “我们来自Qt分享&&交流,我们来自QML分享&&交流”,不管你是笑了,还是笑了,反正我们是认真的。我们就是要找寻一种Hold不住的状态,来开始每一天的点滴分享,我们是一个有激情,有态度...

u011012932
2015/12/12
0
0
Qt自定义控件的创建与初步使用

本篇博客的目的是简单介绍:创建一个用QLabel类来显示图片的自定义控件的编写。在写自定义控件的过程中遇到了很多的难题,但都慢慢解决了,本人对Qt自定义控件的认识还不深刻,做的不对的地方...

qq_15094525
2017/01/06
0
0
中国智能设备制造企业股份有限公司/LibQQt

LibQQt LibQQt全名QQt Foundation Class。 LibQQt为基于Qt开发的App提供中间问题处理层,适配桌面、嵌入式以及Android、IOS的开发。 LibQQt为用户自动生成Library SDK,主动帮助用户发布App...

中国智能设备制造企业股份有限公司
04/16
0
0
PyQt5教程(十)——自定义控件

原文:http://zetcode.com/gui/pyqt5/customwidgets/ PyQt5包含种类丰富的控件。但能满足所有需求的控件库是不存在的。通常控件库只提供了像按钮、文本控件、滑块等最常用的控件。但如果需要...

pseudo
2016/02/16
729
0
Qt Designer中自定义控件的使用(提升法与插件法)

准备乱写一点Qt自定义Widget在Designer中的使用。可是又不想重复提升法(promotion)及插件法基本用法,因为Manual中Using Custom Widgets with Qt Designer已经说的很清楚了。 使用designer ...

晨曦之光
2012/05/08
5.3K
1
怎样在运行时为Qt Designer添加 删除动态属性

最近在开发Qt 自定义控件。有两种为自定义控件创建动态属性的方式: Q_PROPERTY(bool enableTitle READ readTitleFlag WRITE writeTitleFlag) this->setProperty("item",QVariant(QVariant:......

操轻罗小扇扑流萤它妈
2013/04/11
991
0
基于Qt5的快速开发框架--QCFramer

作为一名Qter,我们都知道Qt的强大带给我们nice的编码体验。伴随着用户交互体验越来越受到重视,移动端UI交互体验的冲击,PC端UI交互体验的提升近在眼前。Qt基于c++的跨平台开发框架,已经帮...

ding465398889
2014/07/04
11.8K
0
Android 开发自动化测试工具--QT4A

QT4A (Quick Test for Android),基于QTA提供面向Android应用的UI测试自动化测试解决方案。 特性介绍 支持Android 2.3 - 6.0版本,需要设备root 支持多设备同时测试 支持跨进程、跨应用测试 ...

peterxiong
2016/10/08
421
0
PyQt 4.5+控件的信号槽事件定义方法

Qt采用信号槽来设定UI界面上元素动作的事件绑定。自Qt4.5开始,引入了一个新的信号槽与事件绑定的方法。界面上控件可以发出的默认内容都已经由Qt库定义好了,我们只需要定义处理方法即可。 ...

徐涛
2012/01/20
0
1
QDemo之前置声明

前置声明 = Forward Declaration 对于一个刚刚接触include写法的童鞋来说, 突然看到很多人用如下写法:不知甚解否? #ifndef DIALOG_H define DIALOG_H include <QDialog> //! [前置声明]QT...

jannn
2015/10/06
97
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

gRPC学习笔记

gRPC编程流程 1. proto文件定义 proto文件用于定义需要通过gRPC生成的接口,可以理解为接口定义文档 2. 通过构建工具生成服务基类代码-Maven或Gradle 3. 服务端开发 服务端实现类须实现通过构...

OSC_fly
8分钟前
0
0
Docker Mac (三) Dockerfile 及命令

Dockerfile 最近学习docker的时候,遇到一件怪事,关于docker镜像可能会被破坏,还不知道它会有此措施 所以需要了解构建Dockerfile的正确方法 Dockerfile是由一系列命令和参数构成的脚本,这些命...

___大侠
35分钟前
0
0
NetCat Tutorials

Hacking with Netcat part 1: The Basics Hacking with Netcat part 2: Bind and reverse shells Hacking with Netcat part 3: Advanced Techniques 10 Introduction to Netcat - pdf NetCat......

zungyiu
35分钟前
0
0
Android Studio+NDK+Cmake 移植FFmpeg-4.0.2命令行工具

一、编译 参考大神的帖子,亲测一次编译成功:https://blog.csdn.net/bobcat_kay/article/details/80889398 鉴于以前查文档的经验,这里附上编写例子的时间:2018年7月22日 我用的是ubantu,...

她叫我小渝
36分钟前
0
0
mysql创建数据库

登录MYSQL mysql -u root -p 脚本创建数据库WeChat,并制定默认的字符集是utf8mb4。 CREATE DATABASE Wechat DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci; 授权 grant all......

niithub
50分钟前
0
0
svn: Unable to connect to a repository URL 的解决方案

错误图示: 解决办法:清除本地保存的授权信息; 1:右键点击本地文件夹,选择设置; TortoiseSVN -> Settings 2:在弹出的对话框中选择 Saved Data, 右侧选择:授权地方清理所有。 然后点确...

宁哥实战课堂
今天
1
0
sleep与wait的区别

Thread.sleep(XXX)方法消耗CPU吗? 这个知识点是我之前认识一直有错误的一个知识点,在我以前的认识里面,我一直认为Thread.sleep(1000)的这一秒钟的时间内,线程的休眠是一直占用着CPU的时间...

码代码的小司机
今天
1
0
20位活跃在Github上的国内技术大牛 leij 何小鹏 亚信

本文列举了20位在Github上非常活跃的国内大牛,看看其中是不是很多熟悉的面孔? 1. lifesinger(玉伯) Github主页: https://github.com/lifesinger 微博:@ 玉伯也叫射雕 玉伯(王保平),...

海博1600
今天
1
0
Mybatis收集配置

一、Mybatis取Clob数据 1、Mapper.xml配置 <resultMap type="com.test.User" id="user"> <result column="id" property="id"/> <result column="json_data" property="jsonData" ......

星痕2018
今天
1
0
centos7设置以多用户模式启动

1、旧版本linux系统修改inittab文件,在新版本执行vi /etc/inittab 会有以下提示 # inittab is no longer used when using systemd. # # ADDING CONFIGURATION HERE WILL HAVE NO EFFECT ON......

haha360
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部