Qt中使用QPainter绘制阴影

news/2024/10/7 17:03:01/

困扰了很久的问题,今天终于明白了如何绘制QGraphicDropShadowEffect同样效果的阴影,故写下这篇文章分享给大家。其方法是复制Qt源代码中QGraphicDropShadowEffect绘制实现的核心代码然后稍作修改实现,先看效果和封装过后的源代码:
draw-shadow
头文件:

#pragma once#include <qwidget.h>class CustomWidget : public QWidget {
public:explicit CustomWidget(QWidget *parent = nullptr);protected:void paintEvent(QPaintEvent *event) override;private:/*** @brief 为对象绘制阴影* @param painter* @param shadowObjectPixCache 对象临时缓冲图形* @param pos 绘制位置* @param blurRadius 阴影半径* @param color 阴影颜色* @param offset 偏移*/static void drawShadow(QPainter* painter, const QPixmap &shadowObjectPixCache, const QPointF& pos, qreal blurRadius, const QColor &color, const QPointF &offset);
};

源文件:

#include "customwidget.h"#include <qpainter.h>
#include <qmath.h>CustomWidget::CustomWidget(QWidget *parent): QWidget(parent)
{}void CustomWidget::paintEvent(QPaintEvent *event) {QPainter painter(this);painter.fillRect(rect(), 0x35363C);QRect drawRect(0, 0, 100, 100);// 创建缓存图片在上面绘制图形QPixmap cacheImage(drawRect.width(), drawRect.height());cacheImage.fill(Qt::transparent);QPainter cachePainter(&cacheImage);cachePainter.setRenderHint(QPainter::Antialiasing);cachePainter.setBrush(QColor(0x26282D));cachePainter.setPen(Qt::NoPen);// 绘制一个圆角矩形cachePainter.drawRoundedRect(drawRect, 9, 9);cachePainter.end();// 左上角auto topLeft = rect().center() - drawRect.center();// 绘制图片和阴影drawShadow(&painter, cacheImage, topLeft, 6, 0x6B6F79, QPointF(0, 0));
}// Qt internal function (qtbase/src/widgets/effects/qpixmapfilter.cpp)
extern void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed);// qtbase/src/widgets/effects/qpixmapfilter.cpp: line 1317
void CustomWidget::drawShadow(QPainter* painter, const QPixmap &shadowObjectPixCache, const QPointF& pos, qreal blurRadius, const QColor &color, const QPointF &offset) {// temp render objectQImage tmp(shadowObjectPixCache.size() + QSize(qCeil(blurRadius * 2), qCeil(blurRadius * 2)), QImage::Format_ARGB32_Premultiplied);tmp.setDevicePixelRatio(shadowObjectPixCache.devicePixelRatioF());tmp.fill(0);QPainter tmpPainter(&tmp);tmpPainter.setCompositionMode(QPainter::CompositionMode_Source);tmpPainter.drawPixmap(QPointF(blurRadius, blurRadius) + offset, shadowObjectPixCache);tmpPainter.end();// blur the alpha channelQImage blurred(tmp.size(), QImage::Format_ARGB32_Premultiplied);blurred.setDevicePixelRatio(shadowObjectPixCache.devicePixelRatioF());blurred.fill(0);QPainter blurPainter(&blurred);qt_blurImage(&blurPainter, tmp, blurRadius, false, true, 0);blurPainter.end();tmp = std::move(blurred);// blacken the image...tmpPainter.begin(&tmp);tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);tmpPainter.fillRect(tmp.rect(), color);tmpPainter.end();// draw shadow imagepainter->drawImage(pos - QPointF(blurRadius, blurRadius), tmp);// draw source imagepainter->drawPixmap(pos, shadowObjectPixCache);
}

跟上面的示例一样,在绘制阴影之前先创建一个缓存图片,再调用drawShadow创建阴影。上面代码中的drawShadow正是复制的Qt源代码qtbase/src/widgets/effects/qpixmapfilter.cpp第1317行(Qt5.15.2)的阴影绘制函数,然后稍作修改实现。然后其中用到的一个关键函数qt_blurImage为Qt内部函数,这里仅声明就可以直接导出来使用。看了源代码后就明白了为什么有时候QGraphicDropShadowEffect绘制效率很低界面卡顿,其原因是创建了两个相同大小的临时图片和qt_blurImage的计算导致的。因此在使用该方法的时候,最好使用双缓冲的方式在大小不变的情况下只绘制一次阴影。其他类型的阴影都可以参考qpixmapfilter.cpp中的实现。


http://www.ppmy.cn/news/1535787.html

相关文章

Final Glory推出“荣耀勋章-神龙”,推动游戏叙事范式发展

GameFi赛道因基建设施的缺失而长期处于加密市场的边缘位置&#xff0c;该叙事在市场中的占有率正在下降。不过好的一面是&#xff0c;随着MetaArena引擎面向市场&#xff0c;正在推动区块链游戏市场的叙事向全新的范式发展。 MetaArena引擎是以零知识证明方案为基础的Web3游戏基…

微服务实战——SpringCache 整合 Redis

SpringCache 整合 Redis 1.配置 spring.cache.typeredis EnableCaching EnableFeignClients(basePackages "com.cwh.gulimall.product.feign") EnableDiscoveryClient SpringBootApplication public class GulimallProductApplication {public static void main(…

Web安全 - 构建全面的业务安全保护防御体系

文章目录 业务安全概述业务安全 vs. 基础安全业务安全的防护业务安全的防护策略1. 用户资源对抗的技术实现与优化2. IP资源对抗的技术实现与优化3. 设备资源对抗的技术实现与优化4. 操作资源对抗的技术实现与优化实际应用场景中的策略 典型场景业务场景 1&#xff1a;新用户注册…

长安UNIZ酷狗音乐闪退死机问题【解决方法】

简介 长安UNIZ车友反馈长安uniz车机经常闪退死机&#xff0c;原因是酷狗音乐的问题。酷狗音乐打开后直接闪退。所以长安汽车官方紧急发布了一个更新包解决这个问题&#xff0c;不得不说&#xff0c;长安汽车还是可以的。下面我把安装包放到文章底部。大家下载到u盘后自行安装到…

五子棋双人对战项目(4)——匹配模块(解读代码)

目录 一、约定前后端交互接口的参数 1、websocket连接路径 2、构造请求、响应对象 二、用户在线状态管理 三、房间管理 1、房间类&#xff1a; 2、房间管理器&#xff1a; 四、匹配器(Matcher) 1、玩家实力划分 2、加入匹配队列&#xff08;add&#xff09; 3、移除…

指针(6)

目录 1. 回调函数是什么&#xff1f; 2. qsort 使⽤举例 使⽤qsort函数排序整型数据 ​编辑3. qsort函数的模拟实现 1. 回调函数是什么&#xff1f; 回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数的指针&#xff08;地址&#xff09;作为参数传递给另⼀个函数&…

高防服务器的优劣势有哪些?

高防服务器是专门用于防御分布式拒绝服务攻击和其他网络攻击所设计的服务器&#xff0c;高防服务器可以用于保护企业网站和应用不会受到网络攻击&#xff0c;但是高防服务器咋某些方面还是有着一些不足的&#xff0c;下面我们就来一起了解一下吧&#xff01; 高防服务器通常都具…

php基础语法

PHP 是一种常用于 Web 开发的服务器端脚本语言&#xff0c;具有易于学习、灵活性强等特点。以下是 PHP 的基础语法详细介绍。 1. PHP 基本语法 PHP 文件扩展名&#xff1a;PHP 文件通常以 .php 作为扩展名。 PHP 标签&#xff1a;PHP 代码通常嵌入到 HTML 中&#xff0c;PHP …