千家信息网

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

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,好久没有使用Qt了,最近在做窗体时做了一个自定义的钮铵,刚开始是想通过修改其MASK和ICON的方式来实现。确发现效果总是不太如意,如是干脆自已定义了一个XPushButton。也将其实现方式记录发布
千家信息网最后更新 2026年11月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();
}



0