//!
//! 随笔:Qt变色图像三态按钮
//!
//! == 控件简介 ==
//! 本次提供继承QWidget的按钮控件,提供显示图片功能,
//! 可根据图片透明度设置前景色和后景色,可添加边框和设置保持进入状态颜色,
//! 提供sn_clicked信号(鼠标抬起时发出)
//! == 控件简介 ==
//!
//! 结束语:
//! 文章后提供qbutt_col.h和qbutt_col.cpp文件
//!
#include "../qbutt_col.h"
#include "widget.h"
#include <iostream>
#include <QApplication>
using namespace std;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
qbutt_col bu1(&w);
bu1.set_pic("/home/red/open/github/qt_hur/pic/m_one/m_2.png");
bu1.set_col_foreground({0x808080,0x101010,0xff0000}); //前景色
bu1.set_col_background({0xffaa44,0xff0000,0xffff00}); //背景色
bu1.set_frame(true,QPen(QColor(0x010000),6)); //设置边框(宽度设置偶数可居中)
bu1.show();
w.connect(&bu1,&qbutt_col::sn_clicked,&w,[](){
cout<<"sn_clicked"<<endl;
});
qbutt_col bu2(&w);
bu2.move(bu1.width()+10,0);
bu2.set_pic("/home/red/open/github/qt_hur/pic/m_one/m_2.png",100,200);
bu2.set_col_foreground({0x808080,0x101010,0xff0000}); //前景色
bu2.set_col_background({0xffaa44,0xff0000,0xffff00}); //背景色
bu2.set_frame(true,QPen(QColor(0x010000),6)); //设置边框(宽度设置偶数可居中)
bu2.set_keep_col(true); //保持进入颜色
bu2.show();
w.connect(&bu2,&qbutt_col::sn_clicked,&w,[](){
cout<<"sn_clicked"<<endl;
});
return a.exec();
}
//!
//! qbutt_col.h
//!
#ifndef QBUTT_COL_H
#define QBUTT_COL_H
#include <QWidget>
#include <QPainter>
#include <QWidget>
#include <QMouseEvent>
//!
//! 功能:图片变色三态按钮
//! 用法:传入一张PNG图片(推荐黑白图片),传入三态RGB颜色,触发三态时根据RGB颜色改变图片颜色
//! 原理:保留PNG图片每个点位的颜色信息和透明度,如果点为不透明,根据三态RGB颜色改变点为颜色
//! 注意:前景指有颜色的像素点,背景指透明的像素点
//!
class qbutt_col : public QWidget
{
Q_OBJECT
public:
struct status
{
QColor normal;
QColor enter;
QColor press;
};
public:
explicit qbutt_col(QWidget *parent = nullptr);
bool set_pic(QString pic,int w = 0,int h = 0); //设置图片
void set_col_foreground(status col); //设置前景变化颜色
void set_col_background(status col); //设置背景变化颜色
void set_keep_col(bool keep); //保持进入状态颜色
void set_frame(bool frame,QPen pen); //保持进入状态颜色 (QPen-width双倍数值可居中)
signals:
emit void sn_clicked();
protected:
//绘图事件
void paintEvent(QPaintEvent *event) override;
//触发事件
void enterEvent(QEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void leaveEvent(QEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
//改变像素点颜色
void ch_col_point(QColor col_fore,QColor col_back);
private:
bool _keep_col = false; //保存进入颜色
bool _load_pic = false; //加载图片
bool _paint_frame = false; //边框
bool _paint_fore = false; //前景
bool _paint_back = false; //背景
status _fore; //前景
status _back; //背景
QPen _pen_frame; //边框颜色
QPixmap _pix; //显示图片
QVector<QVector<int>> _vec_alpha; //记录像素点透明度
};
#endif // QBUTT_COL_H
//!
//! qbutt_col.cpp
//!
#include "qbutt_col.h"
qbutt_col::qbutt_col(QWidget *parent) : QWidget(parent)
{
}
bool qbutt_col::set_pic(QString pic,int w,int h)
{
_load_pic = _pix.load(pic);
if(_load_pic)
{
//载入图片,保存透明度像素点
if(w != 0 || h != 0) _pix = _pix.scaled(w,h); //设置缩放
QImage img = _pix.toImage();
_vec_alpha.resize(img.width());
for(int w=0;w<img.width();w++)
{
_vec_alpha[w].resize(img.height());
for(int h=0;h<img.height();h++)
{
_vec_alpha[w][h] = img.pixelColor(w, h).alpha();
}
}
this->resize(img.size()); //重置大小到图片尺寸
}
return _load_pic;
}
void qbutt_col::set_col_foreground(status col)
{
_paint_fore = true;
_fore = col;
ch_col_point(_fore.normal,_back.normal);
}
void qbutt_col::set_col_background(status col)
{
_paint_back = true;
_back = col;
ch_col_point(_fore.normal,_back.normal);
}
void qbutt_col::set_keep_col(bool keep)
{
_keep_col = keep;
}
void qbutt_col::set_frame(bool frame,QPen pen)
{
_paint_frame = frame;
_pen_frame = pen;
}
void qbutt_col::paintEvent(QPaintEvent *event)
{
if(_load_pic)
{
QPainter *show = new QPainter(this);
show->drawPixmap(0,0,_pix);
if(_paint_frame)
{
show->setPen(_pen_frame);
show->drawRect(this->rect());
}
show->end();
}
else QWidget::paintEvent(event);
}
void qbutt_col::enterEvent(QEvent *event)
{
ch_col_point(_fore.enter,_back.enter);
QWidget::enterEvent(event);
}
void qbutt_col::mousePressEvent(QMouseEvent *event)
{
ch_col_point(_fore.press,_back.press);
QWidget::mousePressEvent(event);
}
void qbutt_col::leaveEvent(QEvent *event)
{
if(_keep_col == false) { ch_col_point(_fore.normal,_back.normal); }
QWidget::leaveEvent(event);
}
void qbutt_col::mouseReleaseEvent(QMouseEvent *event)
{
if(this->rect().contains(event->pos())) { emit sn_clicked(); }
ch_col_point(_fore.enter,_back.enter);
QWidget::mouseReleaseEvent(event);
}
void qbutt_col::ch_col_point(QColor col_fore,QColor col_back)
{
if(_paint_fore == false) return;
QImage img = _pix.toImage(); //载入
for (int w=0;w<img.width();w++)
{
for (int h=0;h<img.height();h++)
{
if(_vec_alpha[w][h] > 0 && _paint_fore)
{
col_fore.setAlpha(_vec_alpha[w][h]);
img.setPixelColor(w,h,col_fore);
}
else if(_paint_back) { img.setPixelColor(w,h,col_back); }
}
}
_pix = QPixmap::fromImage(img); //保存
this->update();
}
== 测试图片 ==
![](https://i-blog.csdnimg.cn/blog_migrate/d0f5e881c654189330cf86f1b6ddcd2f.png)
![](https://i-blog.csdnimg.cn/blog_migrate/b62c028237283539b42a78e025862f29.png)
![](https://i-blog.csdnimg.cn/blog_migrate/cbddd955b5bfda5d2c8fb249003c0cdf.png)