QT实现图片开关控件-自定义控件

news2024/11/14 13:26:30

        开关按钮大家应该很熟悉,在设置里面经常遇到,切换时候的滑动效果比较帅气。通常说的开关按钮,有两个状态:on、off。大部分的开关按钮控件,基本上有两大类,第一类是纯代码绘制,这种对代码的掌控度要求比较高,但是灵活性比较好。第二类是贴图,专业的美工做好的各种状态的背景图片,只需要用代码将该图片画到界面上即可。下面,先介绍一种利用贴图来实现的开关按钮。想看纯代码实现的开关按钮请移步:

https://blog.csdn.net/u012959478/article/details/140430844

一、简述

         使用QT实现图片开关控件,即各种状态的背景图片实现开关按钮。

二、 设计思路

        在Qt中,可以通过继承QWidget类来创建一个自定义的图片开关控件。以下是一个简单的自定义控件示例,它可以显示一个带有两种状态的图片(开启和关闭),并且可以通过鼠标点击进行切换状态。        

实现带贴图的开关按钮可以按照以下步骤进行:

  1. 导入需要使用的贴图文件,并添加到项目资源中。
  2. 设计一个开关按钮。
  3. 设置按钮的初始状态,并加载对应的贴图。
  4. 在按钮的点击事件中,切换按钮的状态,并更新贴图。
  5. 根据按钮的状态,执行相应的操作。
三、效果 

四、核心代码  
1、头文件
#ifndef IMAGESWITCH_H
#define IMAGESWITCH_H

#include <QWidget>
class ImageSwitch : public QWidget
{
    Q_OBJECT
    Q_ENUMS(ButtonStyle)

    Q_PROPERTY(bool isChecked READ getChecked WRITE setChecked)
    Q_PROPERTY(ButtonStyle buttonStyle READ getButtonStyle WRITE setButtonStyle)

public:
    enum ButtonStyle {
        ButtonStyle_1 = 0,  //开关样式1
        ButtonStyle_2 = 1,  //开关样式2
        ButtonStyle_3 = 2   //开关样式3
    };

    explicit ImageSwitch(QWidget *parent = 0);

protected:
    void mousePressEvent(QMouseEvent *);
    void paintEvent(QPaintEvent *event);

private:
    bool isChecked;             //是否选中
    ButtonStyle buttonStyle;    //按钮样式

    QString imgOffFile;         //关闭图片
    QString imgOnFile;          //开启图片
    QString imgFile;            //当前图片

public:
    //默认尺寸和最小尺寸
    QSize sizeHint() const;
    QSize minimumSizeHint() const;

    //获取和设置是否选中
    bool getChecked() const;
    void setChecked(bool isChecked);

    //获取和设置按钮样式
    ButtonStyle getButtonStyle() const;
    void setButtonStyle(const ImageSwitch::ButtonStyle &buttonStyle);

Q_SIGNALS:
    void checkedChanged(bool checked);
};

#endif // IMAGESWITCH_H
2、实现代码
#include "imageswitch.h"
#include <QPainter>

ImageSwitch::ImageSwitch(QWidget *parent) : QWidget(parent)
{
    isChecked = false;
    buttonStyle = ButtonStyle_2;

    imgOffFile = ":/image/imageswitch/btncheckoff2.png";
    imgOnFile = ":/image/imageswitch/btncheckon2.png";
    imgFile = imgOffFile;
}

void ImageSwitch::mousePressEvent(QMouseEvent *)
{
    imgFile = isChecked ? imgOffFile : imgOnFile;
    isChecked = !isChecked;
    Q_EMIT checkedChanged(isChecked);
    this->update();
}

void ImageSwitch::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setRenderHints(QPainter::SmoothPixmapTransform);
    QImage img(imgFile);
    img = img.scaled(this->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);

    //按照比例自动居中绘制
    int pixX = rect().center().x() - img.width() / 2;
    int pixY = rect().center().y() - img.height() / 2;
    QPoint point(pixX, pixY);
    painter.drawImage(point, img);
}

QSize ImageSwitch::sizeHint() const
{
    return QSize(87, 28);
}

QSize ImageSwitch::minimumSizeHint() const
{
    return QSize(87, 28);
}

bool ImageSwitch::getChecked() const
{
    return isChecked;
}

void ImageSwitch::setChecked(bool isChecked)
{
    if (this->isChecked != isChecked) {
        this->isChecked = isChecked;
        imgFile = isChecked ? imgOnFile : imgOffFile;
        this->update();
    }
}

ImageSwitch::ButtonStyle ImageSwitch::getButtonStyle() const
{
    return this->buttonStyle;
}

void ImageSwitch::setButtonStyle(const ImageSwitch::ButtonStyle &buttonStyle)
{
    if (this->buttonStyle != buttonStyle) {
        this->buttonStyle = buttonStyle;

        if (buttonStyle == ButtonStyle_1) {
            imgOffFile = ":/image/imageswitch/btncheckoff1.png";
            imgOnFile = ":/image/imageswitch/btncheckon1.png";
            this->resize(87, 28);
        } else if (buttonStyle == ButtonStyle_2) {
            imgOffFile = ":/image/imageswitch/btncheckoff2.png";
            imgOnFile = ":/image/imageswitch/btncheckon2.png";
            this->resize(87, 28);
        } else if (buttonStyle == ButtonStyle_3) {
            imgOffFile = ":/image/imageswitch/btncheckoff3.png";
            imgOnFile = ":/image/imageswitch/btncheckon3.png";
            this->resize(96, 38);
        }

        imgFile = isChecked ? imgOnFile : imgOffFile;
        setChecked(isChecked);
        this->update();
        updateGeometry();
    }
}

        这个自定义控件ImageSwitch提供了基本的开关功能,通过鼠标点击可以在开启和关闭状态之间切换,并且在状态改变时发出一个信号,允许父控件或主窗口作出相应的处理。你可以根据需要对控件进行自定义和扩展。

五、使用示例

以下是一个简单的示例代码,演示了如何在Qt中使用此控件:

#include "frmimageswitch.h"
#include "ui_frmimageswitch.h"
#include "qdebug.h"

frmImageSwitch::frmImageSwitch(QWidget *parent) : QWidget(parent), ui(new Ui::frmImageSwitch)
{
    ui->setupUi(this);
    this->initForm();
}

frmImageSwitch::~frmImageSwitch()
{
    delete ui;
}

void frmImageSwitch::initForm()
{
    ui->imageSwitch1->setChecked(true);
    ui->imageSwitch2->setChecked(true);
    ui->imageSwitch3->setChecked(true);

    ui->imageSwitch1->setFixedSize(160,60);
    ui->imageSwitch2->setFixedSize(160,60);
    ui->imageSwitch3->setFixedSize(160,60);

    ui->imageSwitch1->setButtonStyle(ImageSwitch::ButtonStyle_1);
    ui->imageSwitch2->setButtonStyle(ImageSwitch::ButtonStyle_2);
    ui->imageSwitch3->setButtonStyle(ImageSwitch::ButtonStyle_3);

    //绑定选中切换信号
    connect(ui->imageSwitch1, SIGNAL(checkedChanged(bool)), this, SLOT(checkedChanged(bool)));
    connect(ui->imageSwitch2, SIGNAL(checkedChanged(bool)), this, SLOT(checkedChanged(bool)));
    connect(ui->imageSwitch3, SIGNAL(checkedChanged(bool)), this, SLOT(checkedChanged(bool)));
}

void frmImageSwitch::checkedChanged(bool checked)
{
    qDebug() << sender() << checked;
}

        在上面的示例中,按钮的初始状态为开启,通过设置按钮的 setchecked 进行状态切换。在切换状态时,根据按钮的状态加载对应的贴图,并设置贴图的大小。同时,根据按钮的状态进行相应的操作。需要注意的是,示例中的 on.png 和 off.png 是虚拟的贴图文件,请根据实际情况导入和设置贴图。

        谢谢你的关注和阅读,希望我的回答能帮到你。如果还有其他问题,欢迎随时向我提问。祝你一切顺利!

六、源代码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1933457.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SD-WAN组网搭建5G备份方案实现方式

SD-WAN&#xff08;Software-Defined Wide Area Network&#xff0c;软件定义广域网&#xff09;结合5G作为备份链路是现代企业网络弹性策略的一部分&#xff0c;尤其是在需要高可用性和快速故障切换的场景下。以下是实现SD-WAN组网并集成5G备份方案的一般步骤&#xff1a; 1. …

Spring完整知识点汇总一

Spring简介 额外知识点 在之前的学习中我们在Service业务层创建Dao/Mapper数据访问层&#xff08;持久层&#xff09;的对象是通过工具类来获取对应Dao/Mapper数据访问层&#xff08;持久层&#xff09;的接口代理对象在此处我们不用工具类来获取对应Dao/Mapper数据访问层&…

WebPack5.0 快速入门

前端工程化WebPack5️⃣ 前置知识&#xff1a; 此文章属于前端——框架进阶篇&#xff0c;需要实现掌握&#xff1a;HTMLCSSJS三件套、Node... &#x1f600;推荐分享一波个人Blog文档&#xff1a; JavaScript、前端工程\模块化、邂逅Node.JS的那一夜 什么是WebPack❓ Web…

飞凌全志T527开发板modbus移植使用教程

交叉编译 进入到源码目录&#xff0c;执行 ./configure ac_cv_func_malloc_0_nonnullyes --hostaarch64-none-linux-gnu --enable-static --prefix/home/feng/文档/development/Linux/application/OK527N/libmodbus-3.1.10/install/其中–host为交叉编译器的前缀&#xff1b;…

谈一谈一条SQL的查询、更新语句究竟是如何执行的?

文章目录 理解执行流程衍生知识redo logbinlog 本篇文章是基于《MySQL45讲》来写的个人理解与感悟。 理解 先看下图&#xff1a; 上一篇文章我们讨论了一条SQL查询语句的执行流程&#xff0c;并介绍了执行过程中涉及的处理模块。 回顾一下&#xff1a; 大体来说&#xff0c;…

RK3568笔记三十九:多个LED驱动开发测试(设备树)

若该文为原创文章&#xff0c;转载请注明原文出处。 通过设备树配置一个节点下两个子节点控制两个IO口&#xff0c;一个板载LED&#xff0c;一个外接LED。 一、介绍 通过学习设备树控制GPIO&#xff0c;发现有多种方式 一、直接通过寄存器控制 二、通过设备树&#xff0c;但…

【中项】系统集成项目管理工程师-第一模块:IT技术和管理-1.5数字化转型与元宇宙

前言&#xff1a;系统集成项目管理工程师专业&#xff0c;现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 备注&#xff1a;IT技术和管理-1.4章节涉及敏感&#xff0c;无法发送&#xff0c;故跳过。 软考同样是国家人社部和工信部组织的国家级考试…

工业三防平板适用于各种工业场景

在当今高度工业化的时代&#xff0c;工业三防平板作为一种专为恶劣工业环境设计的设备&#xff0c;正逐渐成为各种工业场景中不可或缺的一部分。 工业三防平板具备出色的防水、防尘和防摔性能&#xff0c;这使得它能够在潮湿、多尘以及容易发生碰撞的环境中稳定运行。无论是在矿…

“富二代”用英语怎么说?真的不是“second rich”!成人英语学习柯桥学外语到蓝天广场

看了沈腾马丽新电影《抓娃娃》&#xff0c;笑得前仰后合。遇上“不靠谱”的爹妈硬是要穷养孩子&#xff0c;就算是“富二代”日子也不好过啊&#xff01; 想必很多人小时候都幻想过&#xff1a;自己的爸妈其实是大富豪&#xff0c;为了磨练自己才假装没钱的。随着逐渐长大才不得…

【内网Tesla T4_16G为例】GPU安装NVIDIA Driver、CUDA、cuDNN、Python

这篇文章主要记录下在内网(无法连接外网)服务器安装NVIDIA Driver、CUDA、cuDNN、Python的过程&#xff0c;机器配置GPU&#xff1a;1*NVIDIA T4 16G&#xff0c;CPU&#xff1a;8C42G&#xff0c;操作系统&#xff1a;GPU-RHEL7.9-x86-64。 想了解如何内网部署ollama&#xf…

数据结构(双向链表)

链表的分类 链表的结构⾮常多样&#xff0c;以下情况组合起来就有8种&#xff08;2 x 2 x 2&#xff09;链表结构&#xff1a; 虽然有这么多的链表的结构&#xff0c;但是我们实际中最常⽤还是两种结构&#xff1a;单链表和双向带头循环链表 1.⽆头单向⾮循环链表&#xff1a…

【ROS2】高级:解锁 Fast DDS 中间件的潜力 [社区贡献]

目标&#xff1a;本教程将展示如何在 ROS 2 中使用 Fast DDS 的扩展配置功能。 教程级别&#xff1a;高级 时间&#xff1a;20 分钟 目录 背景 先决条件在同一个节点中混合同步和异步发布 创建具有发布者的节点创建包含配置文件的 XML 文件执行发布者节点创建一个包含订阅者的节…

AI伦理挑战:构建未来信任的桥梁

在人工智能(AI)技术蓬勃发展的今天&#xff0c;其伦理挑战如同双刃剑的另一面&#xff0c;日益成为全球关注的焦点。面对隐私侵犯、算法偏见、信息真实性危机等伦理困境&#xff0c;我们需要构建全面而精细的应对策略&#xff0c;确保技术进步的同时&#xff0c;守护人类社会的…

MimicMotion-腾讯开源视频生成框架

腾讯宣布开源可控视频生成框架 MimicMotion&#xff0c;该框架可以通过提供参考人像及由骨骼序列表示的动作&#xff0c;来产生平滑的高质量人体动作视频 MimicMotion 具有以下几个亮点&#xff1a; 首先&#xff0c;通过引入了置信度感知的姿态引导信号&#xff0c;大幅提升了…

读书笔记:改善既有代码的设计

差不多两年都没写过博客了&#xff0c;好学的习惯差不多都落下了&#xff0c;两年里几乎也把学到的很多东西都应用了&#xff0c;但不学习好像就有点停步不前的感觉了&#xff0c;以后给自己定个目标每周写一遍博客。 写博客好处&#xff1a; 一是加深自己的印象&#xff08;能…

幽微之处见真章:数据类型与内存存储的内在联系

嘿嘿,家人们,今天咱们来深度剖析数据类型在内存中的存储,好啦,废话多不讲,开干! 1.:数据类型介绍 在前面呢,博主已经介绍了基本的数据类型: char //字符数据类型 ---->占据1个字节 short //短整型 …

51单片机STC89C52RC——18.1 HC-SR04超声波测距

目的/效果 独立按键K1按下后开始测距&#xff0c;LCD显示距离&#xff08;mm&#xff09; 一&#xff0c;STC单片机模块 二&#xff0c;HC-SR04 超声波测距 2.1 HC-SR04 简介 HC-SR04超声波测距模块提供2cm~400cm的测距功能&#xff0c;精度达3mm。 2.2 时序 以上时序图表明…

前端面试题(JS篇五)

一、同步与异步的区别 同步指的是当一个进程在执行某一个请求的时候&#xff0c;如果这个请求需要等待一段时间才能返回&#xff0c;那么这个进程会一直等待下去&#xff0c;直到这个消息返回之后才会继续执行。 指的是当一个进程在执行某一个请求的时候&#xff0c;如果这个请…

Leetcode 1302.层数最深子叶结点的和

大家好&#xff0c;今天我给大家分享一下我关于这个题的想法&#xff0c;我这个题过程比较复杂&#xff0c;但大家如果觉得好的话&#xff0c;就请给个免费的赞吧&#xff0c;谢谢了^ _ ^ 1.题目要求: 给你一棵二叉树的根节点 root &#xff0c;请你返回 层数最深的叶子节点的…

初学者如何通过建立个人博客盈利

建立个人博客不仅能让你在网上表达自己&#xff0c;还能与他人建立联系。通过博客&#xff0c;可以创建自己的空间&#xff0c;分享想法和故事&#xff0c;并与有相似兴趣和经历的人交流。 本文将向你展示如何通过建立个人博客来实现盈利。你将学习如何选择博客主题、挑选合适…