欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Qt之使用QGraphicsDropShadowEffect添加窗口边框以及文字阴影效果

程序员文章站 2024-03-03 19:17:16
...

一、简述

QGraphicsDropShadowEffect继承自QGraphicsEffect,实现了一种阴影的图像效果。
我们在Qt助手中看到QGraphicsEffect派生了四个子类,分别实现不同的效果。

Qt之使用QGraphicsDropShadowEffect添加窗口边框以及文字阴影效果
这里我们看到QGraphicsEffect的子类实现了四种不同的效果,我们可以针对需求选择不同的Effect。今天我们要说的是使用QGraphicsDropShadowEffect来给窗口边框和文字添加阴影效果。

Qt之使用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键我们可以看到,确实啥也没有。那是不是设置了背景透明导致的呢?

Qt之使用QGraphicsDropShadowEffect添加窗口边框以及文字阴影效果

嗯,确实是的,不加 this->setAttribute(Qt::WA_TranslucentBackground); 之后我们看到 去除掉边框之后的窗口就只剩下一团黑,所以这两个条件我们都要加上,但是加上啥也显示不了了呀。确实是的,所以我们要重写paintEvent事件,给窗口添加一个背景。

Qt之使用QGraphicsDropShadowEffect添加窗口边框以及文字阴影效果


重写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));
}

下图我们看到有了一个明显的阴影效果。
Qt之使用QGraphicsDropShadowEffect添加窗口边框以及文字阴影效果


铺垫工作二

现在窗口上没有任何控件,那我们来添加点控件试试。

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);

Qt之使用QGraphicsDropShadowEffect添加窗口边框以及文字阴影效果
修改之后的效果,所以在使用布局的时候要加上一定大小的margin,防止控件越出窗口。(其实控件还是在窗口之上,只是窗口可显示的区域缩小了一圈,在视觉上控件在窗口之外了)
Qt之使用QGraphicsDropShadowEffect添加窗口边框以及文字阴影效果


(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);

黑色文字

Qt之使用QGraphicsDropShadowEffect添加窗口边框以及文字阴影效果

白色文字

Qt之使用QGraphicsDropShadowEffect添加窗口边框以及文字阴影效果


拓展

以上我们讲述了对窗口及文字加上了阴影边框的效果,如果现在我们在paintEvent事件里面不进行任何绘制将是什么效果呢?

我们看到窗口消失了,只有两个按钮和一个Label显示,而阴影效果也渲染在这些控件的周围了。

这下我们知道了阴影会渲染在边框的周围,而文字其实也是有边框的,除了文字内部白色的填充,文字所有笔划的周围都有阴影渲染。所以我们知道QGraphicsDropShadowEffect会在窗口或者控件的边框进行渲染,而如果本体控件没有边框会对其子控件进行渲染。所以这里我们不需要再针对Label进行单独设置阴影了,因为父控件没有了形式上的边框,所以阴影效果渲染在子控件上。
Qt之使用QGraphicsDropShadowEffect添加窗口边框以及文字阴影效果

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

Qt之使用QGraphicsDropShadowEffect添加窗口边框以及文字阴影效果


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

Qt之使用QGraphicsDropShadowEffect添加窗口边框以及文字阴影效果

比如我这篇文字,设置控件背景透明,然后自己绘制一个不规则的图形,也是使用QGraphicsDropShadowEffect,阴影会附着在边框上。


Example

这里测试一下QPushButton控件:

Qt之使用QGraphicsDropShadowEffect添加窗口边框以及文字阴影效果
通过样式表设置按钮没有边框,效果如下图:

Qt之使用QGraphicsDropShadowEffect添加窗口边框以及文字阴影效果
Qt之使用QGraphicsDropShadowEffect添加窗口边框以及文字阴影效果

如果我们给按钮边框去掉,但是加上白色背景,什么效果呢?
我们看到阴影是加在了按钮的边框上,因为有了白色的背景,所有阴影效果附着在了边框附近。

Qt之使用QGraphicsDropShadowEffect添加窗口边框以及文字阴影效果

Qt之使用QGraphicsDropShadowEffect添加窗口边框以及文字阴影效果

现在我们不去掉边框,只加了白色背景,我们看到效果与上面有了很小的区别,就是多了边框。而QPushButton的默认边框其实使用一种凹凸的效果的(在点击按钮的时候),当我们去掉QPushButton的边框时,按钮的样式变成了平面的效果,见上图效果,点击的时候没有凹陷效果。

Qt之使用QGraphicsDropShadowEffect添加窗口边框以及文字阴影效果

通过以上示例,我们再次看到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这几个方法大家可以先看看助手中的解释,自己动手尝试修改参数看看效果,后面会逐一详细说明。