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

    好久没有使用Qt了,最近在做窗体时做了一个自定义的钮铵,刚开始是想通过修改其MASK和ICON的
方式来实现。确发现效果总是不太如意,如是干脆自已定义了一个XPushButton。也将其实现方式记录发
布出来。以方便日后自已使用和给有相应问题的朋友一个小小的提示。
    为了实现任意形状的窗体和保留QPushButton的特性,继承QPushButton创建一个子类。

class QtXPushButton : public QPushButton
{
    Q_OBJECT

public:
    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 <QPushButton>
#include <QString>
#include <QWidget>
#include <QPixmap>

//按钮状态
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 <QBitmap>
#include <QPainter>

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();
}

时间: 2024-10-23 20:38:37

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

使按钮不可用状态下变灰

前台事件.可以给按钮或者其他控件,让他们的不可用状态下的颜色变灰,可用状态下为#A5A7A9这个颜色 $(".aspNetDisabled").attr("disabled", true); $(".aspNetDisabled").each(function (index, item) { $(this).css("text-decoration", "none"); $(this).css("

登录锁定状态下Win7关机技巧总结

登录锁定状态下Win7关机技巧总结 一般在锁定状态都是有个关闭电脑的图标的.但是如果你的系统没有,那么怎么样关机呢,所谓的锁定状态通常是指电脑在登录界面,具体的实现如下,感兴趣的朋友可以参考下 现在大部分的系统,在锁定状态都是有个关闭电脑的图标的.但是如果你的系统没有,那么怎么样关机呢?大部分人用的方法是先登录再关机,所谓的锁定状态通常是指电脑在登录界面. 1.在windows xp和windows 2000系统如果在登录界面没有关闭电脑按钮.那么小编通过是通过更改注册表的设置来搞定的. 2.进

IOS开发——UI进阶篇(十八)核心动画小例子,转盘(裁剪图片、自定义按钮、旋转)图片折叠、音量震动条、倒影、粒子效果

一.转盘(裁剪图片.自定义按钮.旋转) 1.裁剪图片 将一张大图片裁剪为多张 // CGImageCreateWithImageInRect:用来裁剪图片 // image:需要裁剪的图片 // rect:裁剪图片的尺寸,传递是像素 CGImageRef norImage = CGImageCreateWithImageInRect(norBigImage.CGImage, clipRect); 2.每次点击按钮立马变为选中状态,并且取消上次的按钮的选中状态 当然还要重写- (void)setH

xcode UIButton创建、监听按钮点击、自定义按钮 、状态 、内边距

代码创建 //创建UIButton UIButton * btnType=[[UIButton alloc]init]; //设置UIControlStateNormal状态下的文字颜色 [btnType setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; //设置字体大小 btnType.titleLabel.font=[UIFont systemFontOfSize:9.0]; //设置边框的宽度 btnTyp

Qt之模型/视图(自定义按钮)

简述 衍伸前面的章节,我们对QTableView实现了数据显示.自定义排序.显示复选框.进度条等功能的实现,本节主要针对自定义按钮进行讲解,这节过后,也希望大家对自定义有更深入的了解,在以后的功能开发过程中,相信无论遇到什么样式形式,我们都可以很好地实现. 简述 效果 QStyledItemDelegate 源码 衍伸 效果 QStyledItemDelegate 源码 .h 包含显示按钮需要用到的智能指针,按钮的宽度.高度.按钮之间的间距.鼠标的坐标等. class TableViewDele

qt 5 小练习 纯代码制作自定义按钮

大家都知道QT设计师中直接拖动的按钮是长方形带有圆角的图案,那我们如何来设置自定义按钮呢 要设计一个按钮,我们必须要知道按钮有什么属性,首先,按钮必须有一个位置 第二,按钮必须有一个名称.还有当我们点击按钮时他会做出什么样的反应.所以我们定义两个类, 一个QRect _rect; (或者QPoint 更为贴切吧) 第二个是 QString _text; 既然有反应,那我们第一想到的就是鼠标事件,添加一个bool _press; 以及 void mousePressEvent(QMouseEven

5.Qt自定义Button按钮的实现

 1.编写自定义按钮 MyButton.h #ifndef MYBUTTON_H #define MYBUTTON_H #include <QWidget> /** * @brief The MyButton class * 如果想重写button,需要继承QWidget */ class MyButton : public QWidget { Q_OBJECT public: explicit MyButton(QWidget *parent = 0); //重写MyButton的构造函

android 自定义adapter和线程结合 + ListView中按钮滑动后状态丢失解决办法

adapter+线程 1.很多时候自定义adapter的数据都是来源于服务器的,所以在获取服务器的时候就需要异步获取,这里就需要开线程了(线程池)去获取服务器的数据了.但这样有的时候adapter的中没有数据. 如下面的代码: 这就是在initData中异步获取服务器的数据,然后实例化adatper,再将adapter赋给listView. 2.initData()中的代码是: 这里线程要睡眠5秒钟,是为了模仿网络的耗时操作 3.Handler: 在Handler中接收到数据后给list赋值后,

Arcgis for javascript不同的状态下自定义鼠标样式

俗话说:爱美之心,人皆有之.是的,没错,即使我只是一个做地图的,我也希望自己的地图看起来好看一点.在本文,给大家讲讲在Arcgis for javascript下如何自定义鼠标样式. 首先,说几个状态.1.鼠标在地图上面移动:2.按住鼠标左键拖拽鼠标:3.拉框放大地图:4.拉框缩小地图. 鼠标在地图上面时为: 按住鼠标拖拽地图时为: 拉框放大地图时为: 拉框缩小地图时为. 接下来,说说我的实现思路. 第一种状态,在地图加载完成时出现,代码: map.on("load",function