爲了滿足工作中控件多樣性的要求,一些控件的風格需要通過重寫畫家事件的方式進行自定義;
實現sink風格按鈕的效果圖如下:
純代碼實現思路:
產生按鈕下沉的效果是利用了視覺誤差原理,通過更改背景顏色以及圖標的位置,呈現出按鈕動態改變的效果。
按鈕未按下狀態繪製代碼:
void SinkButton::drawUnSinkRect(QPainter *painter)
{
painter->save();
QBrush brush;
brush.setColor(mReleaBgColor);
brush.setStyle(Qt::SolidPattern);
painter->setBrush(brush);
painter->drawRect(0,0,width(),height());
QPen pen;
pen.setColor(mInterColor);
pen.setWidth(mWidth*2);
painter->setPen(pen);
painter->drawLine(width(),0,width(),height());
painter->drawLine(0,height(),width(),height());
pen.setColor(Qt::white);
painter->setPen(pen);
pen.setWidth(0);
painter->drawLine(0,0,width(),0);
painter->drawLine(0,0,0,height());
pen.setColor(Qt::black);
pen.setWidth(0);
painter->setPen(pen);
painter->drawLine(width(),0,width(),height());
painter->drawLine(0,height(),width(),height());
painter->restore();
}
按鈕按下狀態代碼:
void SinkButton::drawSinkedRect(QPainter *painter)
{
painter->save();
QBrush brush;
brush.setColor(mPressBgColor);
brush.setStyle(Qt::SolidPattern);
painter->setBrush(brush);
painter->drawRect(0,0,width(),height());
QPen pen;
pen.setColor(Qt::white);
painter->setPen(pen);
painter->drawLine(width(),0,width(),height());
painter->drawLine(0,height(),width(),height());
pen.setColor(mInterColor);
pen.setWidth(mWidth*2);
painter->setPen(pen);
painter->drawLine(0,0,width(),0);
painter->drawLine(0,0,0,height());
pen.setColor(Qt::black);
pen.setWidth(0);
painter->setPen(pen);
painter->drawLine(0,0,width(),0);
painter->drawLine(0,0,0,height());
painter->restore();
}
完整的源碼:
sinkbutton.h
#ifndef SINKBUTTON_H
#define SINKBUTTON_H
#include <QPushButton>
#include <QColor>
class SinkButton:public QPushButton
{
public:
SinkButton(QWidget *parent = nullptr);
~SinkButton();
void setText(const QString &text);
//其它顏色的設置也可以自己定義接口
void setPressBgColor(const QColor& pressBgColor);
void setReleaBgColor(const QColor& releaseBgColor);
void setIcon(const QString &iconName);
protected:
void paintEvent(QPaintEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void drawText(QPainter *painter);//添加文本
void drawIcon(QPainter *painter);//添加圖標
public slots:
void drawUnSinkRect(QPainter *painter);//正常狀態
void drawSinkedRect(QPainter *painter);//下沉狀態
void drawDisBleRect(QPainter *painter);//禁用狀態
private:
bool pressed;
int mWidth;
int mDisWidth;
QString mText;
QColor mPressBgColor;
QColor mReleaBgColor;
QColor mFrameColor;
QColor mInterColor;
QColor mDisColor;
QColor mDisSlidColor;
QString mIconName;
};
#endif // SINKBUTTON_H
sinkbutton.cpp
#include "sinkbutton.h"
#include <QPainter>
#include <QtDebug>
SinkButton::SinkButton(QWidget *parent):QPushButton(parent)
{
pressed = false;
mWidth = 2;
mDisWidth = 5;
mPressBgColor = QColor("#D8912C");
mReleaBgColor = QColor("#9DBFE6");
mFrameColor = Qt::black;
mInterColor = QColor("#45382B");
mDisColor = QColor("#CBE2F9");
mDisSlidColor = QColor("#514F4F");
mText = "";
mIconName = "";
}
SinkButton:: ~SinkButton()
{
}
void SinkButton::mousePressEvent(QMouseEvent *event)
{
pressed = true;
update();
}
void SinkButton::mouseReleaseEvent(QMouseEvent *event)
{
pressed = false;
update();
}
void SinkButton::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::TextAntialiasing);
if(isEnabled()){
if(!pressed){
drawUnSinkRect(&painter);
}else{
drawSinkedRect(&painter);
}
}else{
drawDisBleRect(&painter);
}
drawIcon(&painter);
drawText(&painter);
}
void SinkButton::drawUnSinkRect(QPainter *painter)
{
painter->save();
QBrush brush;
brush.setColor(mReleaBgColor);
brush.setStyle(Qt::SolidPattern);
painter->setBrush(brush);
painter->drawRect(0,0,width(),height());
QPen pen;
pen.setColor(mInterColor);
pen.setWidth(mWidth*2);
painter->setPen(pen);
painter->drawLine(width(),0,width(),height());
painter->drawLine(0,height(),width(),height());
pen.setColor(Qt::white);
painter->setPen(pen);
pen.setWidth(0);
painter->drawLine(0,0,width(),0);
painter->drawLine(0,0,0,height());
pen.setColor(Qt::black);
pen.setWidth(0);
painter->setPen(pen);
painter->drawLine(width(),0,width(),height());
painter->drawLine(0,height(),width(),height());
painter->restore();
}
void SinkButton::drawSinkedRect(QPainter *painter)
{
painter->save();
QBrush brush;
brush.setColor(mPressBgColor);
brush.setStyle(Qt::SolidPattern);
painter->setBrush(brush);
painter->drawRect(0,0,width(),height());
QPen pen;
pen.setColor(Qt::white);
painter->setPen(pen);
painter->drawLine(width(),0,width(),height());
painter->drawLine(0,height(),width(),height());
pen.setColor(mInterColor);
pen.setWidth(mWidth*2);
painter->setPen(pen);
painter->drawLine(0,0,width(),0);
painter->drawLine(0,0,0,height());
pen.setColor(Qt::black);
pen.setWidth(0);
painter->setPen(pen);
painter->drawLine(0,0,width(),0);
painter->drawLine(0,0,0,height());
painter->restore();
}
void SinkButton::drawDisBleRect(QPainter *painter)
{
painter->save();
QBrush brush;
brush.setColor(mDisColor);
brush.setStyle(Qt::SolidPattern);
painter->setBrush(brush);
painter->drawRect(0,0,width(),height());
QPen pen;
pen.setColor(mDisSlidColor);
pen.setWidth(mDisWidth);
painter->setPen(pen);
painter->drawRect(0,0,width(),height());
painter->restore();
}
void SinkButton::drawInerRect(QPainter *painter)
{
QPen pen;
pen.setStyle(Qt::DotLine);
pen.setColor(mFrameColor);
painter->setPen(pen);
painter->drawRect(mWidth,mWidth,width()-2*mWidth,height()-2*mWidth);
}
void SinkButton::drawText(QPainter *painter)
{
painter->save();
if(pressed){
painter->drawText(mWidth,mWidth,width()-mWidth,height()-mWidth,Qt::AlignCenter,mText);
}else{
painter->drawText(0,0,width(),height(),Qt::AlignCenter,mText);
}
painter->restore();
}
void SinkButton::drawIcon(QPainter *painter)
{
painter->save();
QPixmap pixmap(mIconName);
if(pressed){
painter->drawPixmap((width()-pixmap.width())/2+mWidth,(height()-pixmap.height())/2+mWidth,pixmap.width(),pixmap.height(),pixmap);
}else{
painter->drawPixmap((width()-pixmap.width())/2,(height()-pixmap.height())/2,pixmap.width(),pixmap.height(),pixmap);
}
painter->restore();
}
void SinkButton::setIcon(const QString &iconName)
{
mIconName = iconName;
update();
}
void SinkButton::setText(const QString &text)
{
mText = text;
update();
}
void SinkButton::setPressBgColor(const QColor& pressBgColor)
{
mPressBgColor = pressBgColor;
update();
}
void SinkButton::setReleaBgColor(const QColor& releaBgColor)
{
mReleaBgColor = releaBgColor;
update();
}