本文主要总结一个自定义按钮,该按钮样式效果类似样式表的鼠标悬停(移入)、鼠标移出、鼠标摁下效果。当鼠标分别悬停(移入)、移出、摁下时,其内的图像子控件分别变为对应的图片。下面分别对实现效果进行原理讲解和代码示例。
自定义控件主要是继承QPushbutton的,其中具体的绘制和功能可以参考博主下面两篇博客:
https://blog.csdn.net/naibozhuan3744/article/details/82151007和
https://blog.csdn.net/naibozhuan3744/article/details/102536188。
本文主要讲解样式表效果的鼠标移入(悬停)、鼠标移出、鼠标摁下的效果功能。
实现鼠标移入、移出、摁下效果,主要是用到事件函数,当我们鼠标进入某个控件时,系统会发送一个鼠标移入事件,我们只需要重写QWidget的鼠标移入事件虚函数enterEvent()或者重写QWidget监测所有事件虚函数event(),通过过滤鼠标移入、移出、摁下事件,编写对应的逻辑业务代码。其中,QWidget的事件函数event()原理讲解可以参考这篇别人写的优秀博客:http://mobile.51cto.com/symbian-273119.htm###。本文主要用后面一种方法,通过重写QWidget的事件虚函数event(),监听过对应的鼠标移入、移出、摁下事件,然后编写对应业务逻辑代码。
下面是QWidget的事件虚函数event()声明和定义,以及常用写法模板。
#include
#include
#include
//声明
class QCustomButton : public QPushButton
{
protected:
void enterEvent();
};
//定义
bool QCustomButton::event(QEvent *e)
{
if(this->isChecked())
return QWidget::event(e);
switch (e->type()) {
case QEvent::Enter:
{//鼠标进入事件
//此处写逻辑代码
//return true;
break;
}
case QEvent::MouseButtonPress:
{//鼠标摁下事件
//此处写逻辑代码
//return true;
break;
}
case QEvent::Leave:
{//鼠标离开事件
//此处写逻辑代码
//return true;
break;
}
default:
break;
}
return QWidget::event(e);
}
博主采用的是这种方式的原因主要是因为通用性强,这种方式不但可以监听过滤鼠标事件,还可以监听过滤其它事件,比如键盘摁下事件、硬盘插拔事件、绘图事件、比如定时器溢出事件等所有QWidget自定义的事件,都可以通过重写这个总事件虚函数event进行监听过滤。具体的QWidget所有事件枚举类型,可以参考博主这篇博客:https://blog.csdn.net/naibozhuan3744/article/details/102485019。
注意:这里重写事件函数event,不能返回true,否则原有按钮第一次单击事件会被基类忽略,而形成第一次单击无效的bug,返回QWidget::event(e)基类消息,继续处理后续基类的消息事件。
然后新加一个基类为QPushButton的类QCustomButton。其中类QCustomButton就是自定义的按钮,该按钮布局是上图片下文字,任何间距可以任意调整,同时实现了鼠标移入、移出、摁下按钮时,自定义按钮内的图片自动切换为设置的图片。
当然,调用的时候,需要手动设置鼠标移入、移出、摁下的图片路径,否则不会显示。
qcustombutton.h
#ifndef QCUSTOMBUTTON_H
#define QCUSTOMBUTTON_H
#include
#include
#include
#include
class QCustomButton : public QPushButton
{
public:
explicit QCustomButton(QWidget *parent = nullptr);
void setImageLbl(const QPixmap &pixmap);
void setNormalImagePath(const QPixmap &pixmap);
void setHoverImagePath(const QPixmap &pixmap);
void setPressedImagePath(const QPixmap &pixmap);
void setTextLbl(QString text);
QLabel *getImageHandle();
QLabel *getTextHandle();
protected:
virtual bool event(QEvent *e);
private:
QLabel *imageLbl;
QLabel *textLbl;
QPixmap hoverImage;
QPixmap pressedImage;
QPixmap normalImage;
};
#endif // QCUSTOMBUTTON_H
qcustombutton.cpp
#include
#include
#include
//声明
class QCustomButton : public QPushButton
{
protected:
void enterEvent();
};
//定义
bool QCustomButton::event(QEvent *e)
{
if(this->isChecked())
return QWidget::event(e);
switch (e->type()) {
case QEvent::Enter:
{//鼠标进入事件
//此处写逻辑代码
//return true;
break;
}
case QEvent::MouseButtonPress:
{//鼠标摁下事件
//此处写逻辑代码
//return true;
break;
}
case QEvent::Leave:
{//鼠标离开事件
//此处写逻辑代码
//return true;
break;
}
default:
break;
}
return QWidget::event(e);
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private:
Ui::Widget *ui;
void initUI();
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "qcustombutton.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
initUI();
}
Widget::~Widget()
{
delete ui;
}
void Widget::initUI()
{
QCustomButton *customButton=new QCustomButton(this);
customButton->setImageLbl(QPixmap(":/resource/image/base.png"));
customButton->setNormalImagePath(QPixmap(":/resource/image/base.png"));
customButton->setHoverImagePath(QPixmap(":/resource/image/base_hover.png"));
customButton->setPressedImagePath(QPixmap(":/resource/image/base_pressed.png"));
customButton->setTextLbl("我是text");
customButton->setCheckable(true);
customButton->setFixedSize(300,300);
customButton->setGeometry(0,0,300,300);
// customButton
customButton->show();
customButton->installEventFilter(this);
}
main.cpp
#include "widget.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
由上图结果可知,正常程序显示的是一个小草;当鼠标移入自定义按钮时,图片变成一只蜗牛;当鼠标摁下是图片变成一个电脑台式机;当鼠标移出时,图片再次变成一只蜗牛;实现了鼠标移入、移出、摁下选中分别切换对应图片效果。
程序运行后,出现警告:
libpng warning: iCCP: known incorrect sRGB profile
libpng warning: iCCP: known incorrect sRGB profile
经过查找原因,发现是网上随意下载的*.png图片的问题,只需要换一张正常的图片即可解决警告问题!
参考内容:
http://mobile.51cto.com/symbian-273119.htm###(参考:QEvent原理讲解)
https://blog.csdn.net/naibozhuan3744/article/details/82154880(参考:鼠标事件:移入、摁下、释放)
https://blog.csdn.net/WangJiankun_ls/article/details/79470739(参考:解决警告libpng warning: iCCP: known incorrect sRGB profile)