前言

在Qt界面开发中,很多时候为了UI的整体美观,都会在窗体添加阴影边框,这样会让整个窗体更加漂亮,用户体验会更好,那么,接下来介绍几种在项目中常用的添加阴影边框的方式,其中包括QWidget和QML两个体系的实现方法。而QGraphics体系的阴影边框实现和QWidget是一样的, 可以通用。

正文

一,QWidget实现阴影边框

QWidget实现阴影边框有几种常用的方式,如下:

1.设置带阴影边框的背景图片

这种方式最简单,直接提供一张有阴影边框的背景图片,然后在窗口中继承paintEvent函数(QGraphics体系中是paint函数),通过drawImage或者drawPixmap绘制背景。该方法的优点是实现很简单,也很容易理解。缺点是需要提供一种对应窗口大小的带阴影效果的背景图片,如果尺寸不对,那么在拉伸图片的时候可能会引起模糊的情况,效果就不是很理想。
此方法实现简单,就不单独贴代码了。

2.纯代码绘制阴影边框,没有图片

该方法是使用drawPath函数,通过循环改变阴影边框的颜色然后在窗体四周一层层的绘制阴影,这种方式在实现上较前一种方式更难理解些,代码也相对较多,但是比较通用,并且可以自己调节阴影的区域大小,比较灵活,不需要单独的阴影背景图片 。
关键代码如下:

void ShadowWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainterPath path;
path.setFillRule(Qt::WindingFill);
path.addRect(10,10,this->width()-20,this->height()-20);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
painter.fillPath(path,QBrush(Qt::white));
QColor color(0,0,0,50);
for(int i = 0 ; i < 10
{
QPainterPath path;
path.setFillRule(Qt::WindingFill);
path.addRect(10-i,10-i,this->width()-(10-i)*2,this->height()-(10-i)*2);
color.setAlpha(150 - qSqrt(i)*50);
painter.setPen(color);
painter.drawPath(path);
}
}

这种方式是完全通过算法在窗口边框绘制阴影。

3.纯代码绘制阴影边框,有阴影图片

第三种方式通过一种固定的阴影背景图片,然后截取阴影图片,最后再绘制到窗体的四周。这种方式也很通用,在之前的项目中都用该i方式来实现,代码很容易理解,结构也很清晰。
关键代码如下:

void Widget::paintEvent(QPaintEvent *e)
{
QPainter painter(this);
QRect bottom(5, 136, 200, 7);
QRect top(5, 0, 200, 3);
QRect left(0, 3, 5, 133);
QRect right(205, 3, 5, 133);
QRect topRight(205, 0, 5, 3);
QRect topLeft(0, 0, 5, 3);
QRect bottomLeft(0, 136, 5, 7);
QRect bottomRight(205, 136, 5, 7);
QRect tBottom(5, this->height() - 7, this->width() - 10, 7);
QRect tTop(5, 0, this->width() - 10, 3);
QRect tLeft(0, 3, 5, this->height() - 10);
QRect tRight(this->width() - 5, 3, 5, this->height() - 10);
QRect tTopLeft(0, 0, 5, 3);
QRect tTopRight(this->width() - 5, 0, 5, 3);
QRect tBottomLeft(0, this->height() - 7, 5, 7);
QRect tBottomRight(this->width() - 5, this->height() - 7, 5, 7);
painter.drawPixmap(tBottom, m_shadow, bottom);
painter.drawPixmap(tTop, m_shadow, top);
painter.drawPixmap(tLeft, m_shadow, left);
painter.drawPixmap(tRight, m_shadow, right);
painter.drawPixmap(tTopRight, m_shadow, topRight);
painter.drawPixmap(tTopLeft, m_shadow, topLeft);
painter.drawPixmap(tBottomLeft, m_shadow, bottomLeft);
painter.drawPixmap(tBottomRight, m_shadow, bottomRight);
}

该方式是在边框内用5个像素绘制阴影效果

以下是m_shadow图片,直接右键复制到工程目录下,设置m_shadow即可,以上的方式对widget大小没影响,都能用。

Qt/QML 窗口阴影边框实现_qt

二,QML实现阴影效果

由于QML有着强大的绘图机制,再加上其丰富的动画效果,可以快速实现很复杂的界面,所以QML很适合移动端的开发,而在移动端窗体都是全屏,只有某些窗口部件会有阴影边框,接下来看看QML中对窗口部件的阴影效果实现。

1.给窗口添加BorderImage

这种方式类似于QWidget中通过阴影图片来设置阴影边框的方式,代码结构很简单,前提是需要准备一张阴影的图片。
示例如下:

ShadowRectangle.qml

Item{

property alias color: rectangle.color
property alias source: image.source


BorderImage {
anchors.fill: rectangle
anchors {
leftMargin: -6
topMargin: -6
rightMargin: -8
bottomMargin: -8
}
border {
left: 10
top: 10
right: 10
bottom: 10
}
source: "shadow.png"
smooth: true
}
Rectangle {
id: rectangle
anchors.fill: parent
Image{
id:image
anchors.fill: rectangle
fillMode: Image.PreserveAspectFit
smooth: true
}
}
}

shadows_test.qml

Rectangle {
width: 300
height: 200

color:"gray"

ShadowRectangle{
anchors.centerIn: parent
width: 200
height: 100
color:"blue"
}
ShadowRectangle{
anchors.centerIn: parent
width: 150
height: 70
color:"red"
}
ShadowRectangle{
anchors.centerIn: parent
width: 100
height: 40
// color:"green"
source: "1.jpg"

效果图如下:

Qt/QML 窗口阴影边框实现_阴影_02

2.利用QML提供的组件来实现

QML中自带组件DropShadow可以实现阴影效果,该组件功能很强大, 提供了很多阴影效果,具体的可以查看Qt帮助文档。使用方式也很简单

示例如下:

Item {
width:300
height: 300}

Image {
id:"images/butterfly.png"
sourceSize: Qt.size(parent.width, parent.height)}

DropShadow {
anchors.fill:3
verticalOffset: 3
radius: 8.0
samples: 16
color: "#80000000"}
}

Qt/QML 窗口阴影边框实现_背景图片_03


可以将以上示例中的butterfly图片换成别的组件,一样的可以实现阴影效果,如下示例:

Rectangle {
width:500
height: 500
Rectangle{
width: 300
height: 300
id:rect
anchors.centerIn: parent
color:"red"}

DropShadow {
anchors.fill:3
verticalOffset: 3
radius: 8.0
samples: 16
color: "#80000000"}
}

Qt/QML 窗口阴影边框实现_阴影_04


更多的阴影效果请查看Qt帮助文档。