千家信息网

Qt自定义按钮及不同状态下图片的切换

发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,好久没有使用Qt了,最近在做窗体时做了一个自定义的钮铵,刚开始是想通过修改其MASK和ICON的方式来实现。确发现效果总是不太如意,如是干脆自已定义了一个XPushButton。也将其实现方式记录发布
千家信息网最后更新 2025年12月02日Qt自定义按钮及不同状态下图片的切换
    好久没有使用Qt了,最近在做窗体时做了一个自定义的钮铵,刚开始是想通过修改其MASK和ICON的方式来实现。确发现效果总是不太如意,如是干脆自已定义了一个XPushButton。也将其实现方式记录发布出来。以方便日后自已使用和给有相应问题的朋友一个小小的提示。    为了实现任意形状的窗体和保留QPushButton的特性,继承QPushButton创建一个子类。class QtXPushButton : public QPushButton{    Q_OBJECTpublic:    QtXPushButton(QString strImagePath, QWidget *parent = NULL);    ~QtXPushButton();}

为了方便描述按钮正常、鼠标滑动、选取状态、禁止点击状态定义一个状态枚举。

//按钮状态
enum XBUTTONSTATE
{
NORMAL = 0X01,//正常状态
HOVER = 0X02,//鼠标滑过状态
SELECTED = 0X04,//选中状态
DISABLE = 0X08//禁止点击状态
};


为了方便设置个程状态的图标,添加状态图标设置接口,并设置一个标识表明设置了哪些状态。

//设置正常图标
void SetNormalPixmap(QString strImagePath);
//设置鼠标滑动图片
void SetHoverPixmap(QString strImagePath);
//设置选中状态图片
void SetSelectedPixmap(QString strImagePath);
//设置禁止点击图标
void SetDisablePixmap(QString strImagePath);
//设置按钮当前状态

void SetBtnState(XBUTTONSTATE state);
//设置图片大小
void SetSize(QSize sz);


至此一个具有设置正常、鼠标滑动、选中、禁止点击功能的按钮的接口就定义好了。这个子类的最终定义如下。

#pragma once

#include
#include
#include
#include

//按钮状态
enum XBUTTONSTATE
{
NORMAL = 0X01,//正常状态
HOVER = 0X02,//鼠标滑过状态
SELECTED = 0X04,//选中状态
DISABLE = 0X08//禁止点击状态
};

class QtXPushButton : public QPushButton
{
Q_OBJECT

public:
QtXPushButton(QString strImagePath, QWidget *parent = NULL);
~QtXPushButton();

//设置正常图标
void SetNormalPixmap(QString strImagePath);
//设置鼠标滑动图片
void SetHoverPixmap(QString strImagePath);
//设置选中状态图片
void SetSelectedPixmap(QString strImagePath);
//设置禁止点击图标
void SetDisablePixmap(QString strImagePath);
//设置按钮当前状态
void SetBtnState(XBUTTONSTATE state);
//设置图片大小
void SetSize(QSize sz);

protected:
virtual void paintEvent(QPaintEvent *event);
virtual void enterEvent(QEvent *event);
virtual void leaveEvent(QEvent *event);



private:
QtXPushButton(const QtXPushButton& btn);
QtXPushButton& operator=(const QtXPushButton& btn);

private:
QPixmap m_NormalPix;//正常图标
QPixmap m_HoverPix;//鼠标滑动图标
QPixmap m_SelectedPix;//选中状态图标
QPixmap m_DisablePix;//禁止点击图标
int m_iMask;//包含1则启动正常图标,包含2启用滑动图标,包含4启用选中状态图标,包含8启用禁止点击图标,默认标为1.
XBUTTONSTATE m_curState;//当前状态
XBUTTONSTATE m_lastState;//上一次状态
};


接下来实现其相应功能。实现一个不规则的窗体大至需要做两个动作。

(1)通过REGON或者MASK确定其边框,在构造函数中添加如下代码:

QtXPushButton::QtXPushButton(QString strImagePath, QWidget *parent)
:QPushButton(parent)
{
m_NormalPix.load(strImagePath);
resize(m_NormalPix.size());
setMask(QBitmap(m_NormalPix.mask()));
m_iMask = XBUTTONSTATE::NORMAL;
m_curState = XBUTTONSTATE::NORMAL;
m_lastState = XBUTTONSTATE::NORMAL;
}



(2)在窗体绘制时将图片绘制于其上,重载其绘图函数,添加如下代码。

void QtXPushButton::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.drawPixmap(0, 0, m_NormalPix);
}


上面两个步骤可以实现一个任意规则的自定义窗体,其下来实现其在不同状态下的图片的切换。

设置不同状态的图片,这里以鼠标滑动方式为例。由于鼠标进入窗体区域后就应当设置为鼠标滑动状态,重载窗体的鼠标进入和鼠标离开区域来监测其状态。

//设置鼠标滑动图片
void QtXPushButton::SetHoverPixmap(QString strImagePath)
{
m_HoverPix.load(strImagePath);
m_iMask |= XBUTTONSTATE::HOVER;
}


//重载鼠标进入和移出事件

void QtXPushButton::enterEvent(QEvent *event)
{
SetBtnState(XBUTTONSTATE::HOVER);
QPushButton::enterEvent(event);
update();
}

void QtXPushButton::leaveEvent(QEvent *event)
{
m_curState = m_lastState;
QPushButton::leaveEvent(event);
update();
}


//用指定图片重绘窗体

void QtXPushButton::paintEvent(QPaintEvent *event)
{
QPixmap drawPix;

if (m_curState == XBUTTONSTATE::NORMAL)
{
drawPix = m_NormalPix;
}
else if (m_curState == XBUTTONSTATE::HOVER)
{
int iValue = m_iMask&XBUTTONSTATE::HOVER;
drawPix = (0 == iValue) ? m_NormalPix : m_HoverPix;
}
else if (m_curState == XBUTTONSTATE::SELECTED)
{
int iValue = m_iMask&XBUTTONSTATE::SELECTED;
drawPix = (0 == iValue) ? m_NormalPix : m_SelectedPix;
}
else if (m_curState == XBUTTONSTATE::DISABLE)
{
int iValue = m_iMask&XBUTTONSTATE::DISABLE;
drawPix = (0 == iValue) ? m_NormalPix : m_DisablePix;
}

QPainter painter(this);
painter.drawPixmap(0, 0, drawPix);
}


经过上述过程鼠标进入按钮区域,按钮会显示HOVER图片。鼠标移出按钮区域,按钮会显示鼠标进入之前的状态。


程序完全源码如下:

#include "QtXPushButton.h"
#include
#include

QtXPushButton::QtXPushButton(QString strImagePath, QWidget *parent)
:QPushButton(parent)
{
m_NormalPix.load(strImagePath);
resize(m_NormalPix.size());
setMask(QBitmap(m_NormalPix.mask()));
m_iMask = XBUTTONSTATE::NORMAL;
m_curState = XBUTTONSTATE::NORMAL;
m_lastState = XBUTTONSTATE::NORMAL;
}

QtXPushButton::~QtXPushButton()
{
}

//设置正常图标
void QtXPushButton::SetNormalPixmap(QString strImagePath)
{
m_NormalPix.load(strImagePath);
m_iMask |= XBUTTONSTATE::NORMAL;
}

//设置鼠标滑动图片
void QtXPushButton::SetHoverPixmap(QString strImagePath)
{
m_HoverPix.load(strImagePath);
m_iMask |= XBUTTONSTATE::HOVER;
}

//设置选中状态图片
void QtXPushButton::SetSelectedPixmap(QString strImagePath)
{
m_SelectedPix.load(strImagePath);
m_iMask |= XBUTTONSTATE::SELECTED;
}

//设置禁止点击图标
void QtXPushButton::SetDisablePixmap(QString strImagePath)
{
m_DisablePix.load(strImagePath);
m_iMask |= XBUTTONSTATE::DISABLE;
}

//设置按钮当前状态
void QtXPushButton::SetBtnState(XBUTTONSTATE state)
{
m_lastState = m_curState;
m_curState = state;
}

//设置图片大小
void QtXPushButton::SetSize(QSize sz)
{
m_NormalPix = m_NormalPix.scaled(sz);
int iValue = m_iMask&XBUTTONSTATE::HOVER;

if (iValue != 0)
{
m_HoverPix = m_HoverPix.scaled(sz);
}

iValue = m_iMask&XBUTTONSTATE::SELECTED;

if (iValue != 0)
{
m_SelectedPix = m_SelectedPix.scaled(sz);
}

iValue = m_iMask&XBUTTONSTATE::DISABLE;

if (iValue != 0)
{
m_DisablePix = m_DisablePix.scaled(sz);
}
}

void QtXPushButton::paintEvent(QPaintEvent *event)
{
QPixmap drawPix;

if (m_curState == XBUTTONSTATE::NORMAL)
{
drawPix = m_NormalPix;
}
else if (m_curState == XBUTTONSTATE::HOVER)
{
int iValue = m_iMask&XBUTTONSTATE::HOVER;
drawPix = (0 == iValue) ? m_NormalPix : m_HoverPix;
}
else if (m_curState == XBUTTONSTATE::SELECTED)
{
int iValue = m_iMask&XBUTTONSTATE::SELECTED;
drawPix = (0 == iValue) ? m_NormalPix : m_SelectedPix;
}
else if (m_curState == XBUTTONSTATE::DISABLE)
{
int iValue = m_iMask&XBUTTONSTATE::DISABLE;
drawPix = (0 == iValue) ? m_NormalPix : m_DisablePix;
}

QPainter painter(this);
painter.drawPixmap(0, 0, drawPix);
}

void QtXPushButton::enterEvent(QEvent *event)
{
SetBtnState(XBUTTONSTATE::HOVER);
QPushButton::enterEvent(event);
update();
}

void QtXPushButton::leaveEvent(QEvent *event)
{
m_curState = m_lastState;
QPushButton::leaveEvent(event);
update();
}



状态 鼠标 图标 图片 按钮 窗体 区域 大小 方式 不同 两个 代码 函数 功能 子类 接口 切换 不规则 接下来 事件 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 落实网络安全保密工作责任制 软件开发从业方向 青岛网络技术有限公司 北京互联网科技研究院是什么 12月12日国家网络安全日图片 网络安全周会记录 魔兽世界凤凰之神是哪个服务器的 创建一个数据库实例 空号检测软件开发要多少钱 交通静态数据库 数据库连接池中默认连接数 服务器绑别人二级域名安全吗 数据库四种保护 三月十五网络安全会 我的世界服务器有人却连接不到服务器 怎样建立数据库服务器 软件开发中的配置管理 桌面电脑和服务器有什么区别 邮政寄递四大数据库是指什么 博野县网络安全委员会 网络安全朗读词 网络安全法有下列行为 虎年软件开发门口贴的对联 深圳腾科网络技术有限公司 快快宝网络技术 厦门软件开发工资15k高吗 如何把表转换成数据库 看日志如何连公司服务器 广东光纤网络技术开发商家 网络技术开发市场报价
0