Qt之使用QGraphicsDropShadowEffect添加窗口边框以及文字阴影效果
一、简述
QGraphicsDropShadowEffect继承自QGraphicsEffect,实现了一种阴影的图像效果。
我们在Qt助手中看到QGraphicsEffect派生了四个子类,分别实现不同的效果。
这里我们看到QGraphicsEffect的子类实现了四种不同的效果,我们可以针对需求选择不同的Effect。今天我们要说的是使用QGraphicsDropShadowEffect来给窗口边框和文字添加阴影效果。
二、主角-QGraphicsDropShadowEffect
(1)窗口边框添加阴影效果
代码很简单,主要分为两步:
1、设置窗口为无边框和背景透明,如果没有设置则是windows自己的窗口边框效果,则没有什么意义;背景如果不透明,那如何渲染呢。
2、使用QGraphicsDropShadowEffect给窗口添加合适的阴影效果。
// 1、设置无边框,背景透明
this->setWindowFlags(Qt::FramelessWindowHint);
this->setAttribute(Qt::WA_TranslucentBackground);
// 2、设置阴影边框;
QGraphicsDropShadowEffect* shadowEffect = new QGraphicsDropShadowEffect(this);
// 阴影偏移
shadowEffect->setOffset(0, 0);
// 阴影颜色;
shadowEffect->setColor(Qt::black);
// 阴影半径;
shadowEffect->setBlurRadius(10);
// 给窗口设置上当前的阴影效果;
this->setGraphicsEffect(shadowEffect);
除了添加以上代码之外,还有一些铺垫工作需要做。
铺垫工作一
因为设置了无边框,背景透明,所以当我们直接调用show显示窗口时,其实什么都不会显示出来,用alt + tab键我们可以看到,确实啥也没有。那是不是设置了背景透明导致的呢?
嗯,确实是的,不加 this->setAttribute(Qt::WA_TranslucentBackground); 之后我们看到 去除掉边框之后的窗口就只剩下一团黑,所以这两个条件我们都要加上,但是加上啥也显示不了了呀。确实是的,所以我们要重写paintEvent事件,给窗口添加一个背景。
重写paintEvent事件即可,这里我们填充窗口的时候记得填充的Rect要比原始的窗口小一些,因为要留一些空间绘制边框的阴影。所以这里填充的矩形区域为:
Rect = this->rect().adjusted(SHADOW_WIDTH, SHADOW_WIDTH, -SHADOW_WIDTH, -SHADOW_WIDTH);
(将原来的窗口Rect缩小一圈即可)
void MyDropShadowWindow::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.fillRect(this->rect().adjusted(SHADOW_WIDTH, SHADOW_WIDTH, -SHADOW_WIDTH, -SHADOW_WIDTH), QColor(238, 223, 204));
}
下图我们看到有了一个明显的阴影效果。
铺垫工作二
现在窗口上没有任何控件,那我们来添加点控件试试。
void MyDropShadowWindow::initWidget()
{
QPushButton* pButtonOne = new QPushButton("A");
pButtonOne->setFixedSize(QSize(200, 100));
QPushButton* pButtonTwo = new QPushButton("B");
pButtonTwo->setFixedSize(QSize(200, 100));
QHBoxLayout* hMainLayout = new QHBoxLayout(this);
hMainLayout->addWidget(pButtonOne);
hMainLayout->addWidget(pButtonTwo);
hMainLayout->addStretch();
hMainLayout->setMargin(0);
}
我们可以看到按钮跑出来窗口,所以这里要做一下修改:
hMainLayout->setMargin(0); 要改为 hMainLayout->setMargin(SHADOW_WIDTH);
修改之后的效果,所以在使用布局的时候要加上一定大小的margin,防止控件越出窗口。(其实控件还是在窗口之上,只是窗口可显示的区域缩小了一圈,在视觉上控件在窗口之外了)
(2)文字添加阴影效果
QLabel* pLabel = new QLabel("ABCDEFG");
pLabel->setStyleSheet("font-size:30px;");
QGraphicsDropShadowEffect* shadowEffect = new QGraphicsDropShadowEffect(pLabel);
shadowEffect->setOffset(0, 0);
shadowEffect->setColor(Qt::black);
shadowEffect->setBlurRadius(10);
pLabel->setGraphicsEffect(shadowEffect);
黑色文字
白色文字
拓展
以上我们讲述了对窗口及文字加上了阴影边框的效果,如果现在我们在paintEvent事件里面不进行任何绘制将是什么效果呢?
我们看到窗口消失了,只有两个按钮和一个Label显示,而阴影效果也渲染在这些控件的周围了。
这下我们知道了阴影会渲染在边框的周围,而文字其实也是有边框的,除了文字内部白色的填充,文字所有笔划的周围都有阴影渲染。所以我们知道QGraphicsDropShadowEffect会在窗口或者控件的边框进行渲染,而如果本体控件没有边框会对其子控件进行渲染。所以这里我们不需要再针对Label进行单独设置阴影了,因为父控件没有了形式上的边框,所以阴影效果渲染在子控件上。
下面一张图是去除所有阴影代码之后的效果。
比如我这篇文字,设置控件背景透明,然后自己绘制一个不规则的图形,也是使用QGraphicsDropShadowEffect,阴影会附着在边框上。
Example
这里测试一下QPushButton控件:
通过样式表设置按钮没有边框,效果如下图:
如果我们给按钮边框去掉,但是加上白色背景,什么效果呢?
我们看到阴影是加在了按钮的边框上,因为有了白色的背景,所有阴影效果附着在了边框附近。
现在我们不去掉边框,只加了白色背景,我们看到效果与上面有了很小的区别,就是多了边框。而QPushButton的默认边框其实使用一种凹凸的效果的(在点击按钮的时候),当我们去掉QPushButton的边框时,按钮的样式变成了平面的效果,见上图效果,点击的时候没有凹陷效果。
通过以上示例,我们再次看到QGraphicsDropShadowEffect 的阴影效果会添加在控件的边框附近,而没有边框只有文字的那就会附着在文字周边。
附上文章中提到的完成源码
MyDropShadowWindow.h
#include <QWidget>
class MyDropShadowWindow : public QWidget
{
Q_OBJECT
public:
MyDropShadowWindow(QWidget *parent = NULL);
~MyDropShadowWindow();
private:
void initWidget();
void paintEvent(QPaintEvent *event);
};
MyDropShadowWindow.cpp
#include "MyDropShadowWindow.h"
#include <QGraphicsDropShadowEffect>
#include <QPainter>
#include <QPushButton>
#include <QHBoxLayout>
#include <QLabel>
#define SHADOW_WIDTH 10 // 阴影边框宽度;
MyDropShadowWindow::MyDropShadowWindow(QWidget *parent)
: QWidget(parent)
{
initWidget();
this->setWindowFlags(Qt::FramelessWindowHint);
this->setAttribute(Qt::WA_TranslucentBackground);
// 设置阴影边框;
QGraphicsDropShadowEffect* shadowEffect = new QGraphicsDropShadowEffect(this);
shadowEffect->setOffset(0, 0);
shadowEffect->setColor(Qt::black);
shadowEffect->setBlurRadius(SHADOW_WIDTH);
this->setGraphicsEffect(shadowEffect);
this->setFixedSize(QSize(600, 500));
this->setWindowTitle("MyDropShadowWindow");
}
MyDropShadowWindow::~MyDropShadowWindow()
{
}
void MyDropShadowWindow::initWidget()
{
QPushButton* pButtonOne = new QPushButton("A");
pButtonOne->setFixedSize(QSize(200, 100));
QPushButton* pButtonTwo = new QPushButton("B");
pButtonTwo->setFixedSize(QSize(200, 100));
QLabel* pLabel = new QLabel("ABCDEFG");
pLabel->setStyleSheet("font-size:30px;");
QGraphicsDropShadowEffect* shadowEffect = new QGraphicsDropShadowEffect(pLabel);
shadowEffect->setOffset(0, 0);
shadowEffect->setColor(Qt::black);
shadowEffect->setBlurRadius(15);
pLabel->setGraphicsEffect(shadowEffect);
QHBoxLayout* hMainLayout = new QHBoxLayout(this);
hMainLayout->addWidget(pButtonOne);
hMainLayout->addWidget(pButtonTwo);
hMainLayout->addWidget(pLabel);
hMainLayout->addStretch();
hMainLayout->setMargin(SHADOW_WIDTH);
}
void MyDropShadowWindow::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.fillRect(this->rect().adjusted(SHADOW_WIDTH, SHADOW_WIDTH, -SHADOW_WIDTH, -SHADOW_WIDTH), QColor(238, 223, 204));
}
尾
关于文章开始提到的其他Effect我会在后面的文章中提到,还有setOffset、setBlurRadius、setBlurRadius这几个方法大家可以先看看助手中的解释,自己动手尝试修改参数看看效果,后面会逐一详细说明。
上一篇: Mybatis_ResultMap结果集映射(基础)
下一篇: 图像去暗角