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进行单独设置阴影了,因为父控件没有了形式上的边框,所以阴影效果渲染在子控件上。
在这里插入图片描述

下面一张图是去除所有阴影代码之后的效果。

在这里插入图片描述


Qt如何绘制带小三角的消息框

在这里插入图片描述

比如我这篇文字,设置控件背景透明,然后自己绘制一个不规则的图形,也是使用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这几个方法大家可以先看看助手中的解释,自己动手尝试修改参数看看效果,后面会逐一详细说明。

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页