当前位置: 首页 > news >正文

QWidget窗口抗锯齿圆角的一个实现方案(支持子控件)2

QWidget窗口抗锯齿圆角的一个实现方案(支持子控件)2

本方案使用了QGraphicsEffect,由于QGraphicsEffect对一些控件会有渲染问题,比如列表、表格等,所以暂时仅作为研究,优先其他方案

在之前的文章中(支持子控件的抗锯齿圆角方案),对于独立弹窗的抗锯齿圆角,使用一层遮罩来实现对窗口内容的裁切。

在很早之前还考虑过另外一种方案,既然QGraphicsEffect能够对控件进行一些特效处理,那自定义QGraphicsEffect也应该可以做到对内容裁剪。但当时仅在QComboBox下拉列表上进行了测试,没有达到预期(实际可能是Qt内部的bug),甚至导致了我对QGraphicsEffect原理的误解。

直接说方案。

方案
  1. 重写一个QGraphicsEffect,照着其他Qt提供的类,重写QGraphicsEffect::draw接口。
    简单来说就是通过混合模式对sourcePixmap进行圆角位置的像素清除,支持抗锯齿
void draw(QPainter *painter)
{// 一些Qt的逻辑QPoint offset;Qt::CoordinateSystem system = sourceIsPixmap() ? Qt::LogicalCoordinates : Qt::DeviceCoordinates;QPixmap pixmap = sourcePixmap(system, &offset, QGraphicsEffect::NoPad);if (pixmap.isNull())return;painter->save();QPainter pixmapPainter(&pixmap);pixmapPainter.setRenderHints(QPainter::Antialiasing); // 打开抗锯齿pixmapPainter.setPen(Qt::NoPen);pixmapPainter.setBrush(Qt::red); //颜色不重要,非透明即可pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationOut); // 混合模式,达到清楚圆角部分像素目的QPainterPath path;// _target是目标QWidget,可以通过构造函数自己保存// 区域增大一点,避免边界有残留path.addRect(QRect(QPoint(0, 0), _target->size()).adjusted(-1, -1, 1, 1));path.addRoundedRect(QRect(QPoint(0, 0), _target->size()), 20, 20);// 一些Qt的绘制逻辑if (system == Qt::DeviceCoordinates) {QTransform worldTransform = painter->worldTransform();worldTransform *= QTransform::fromTranslate(-offset.x(), -offset.y());pixmapPainter.setWorldTransform(worldTransform);} else {pixmapPainter.translate(-offset);}pixmapPainter.drawPath(path);pixmapPainter.end();painter->setWorldTransform(QTransform());painter->drawPixmap(offset, pixmap);painter->restore();
};

上述代码里包含Qt的一些代码逻辑,没有具体研究过差异。

  1. 设置给目标控件即可
    下拉框动画过程中会存在一些黑色像素,可以关闭动画。主要还是建议在相对静态的控件中使用。
    在这里插入图片描述
结论

个人理解Qt的QGraphicsEffect里有相当多的问题,较早的版本可能对窗口的子控件无效,后期增加了对子控件的统一渲染支持,直到Qt6.4(应该是这个版本)解决了大部分问题,但对于像列表、表格等存在脏区域优化的控件,仍然存在渲染问题。

http://www.lryc.cn/news/393861.html

相关文章:

  • 数据结构之“队列”(全方位认识)
  • 密码学复习
  • 【文献解析】一种像素级的激光雷达相机配准方法
  • Http 实现请求body体和响应body体的双向压缩方案
  • C++(Qt)-GIS开发-简易瓦片地图下载器
  • 誉天教育7月开班计划:为梦想插上腾飞的翅膀!
  • STM32基础篇:GPIO
  • HTTPS 发送请求出现TLS握手失败
  • 数字化精益生产系统--IFS财务管理系统
  • 基于SpringBoot的校园台球厅人员与设备管理系统
  • 免杀笔记 ---> Session0--DLL注入
  • 如何做好IT类的技术面试?
  • A7 配置方式Master SPI如何更改位宽
  • linux kthread任务管理
  • 第一节 网络安全概述
  • 星光云VR全景系统源码
  • spdlog一个非常好用的C++日志库(七): 源码分析之异常类spdlog_ex
  • 从一次 SQL 查询的全过程了解 DolphinDB 线程模型
  • Vue3.js“非原始值”响应式实现基本原理笔记(二)
  • 论文 | PRCA: 通过可插拔奖励驱动的上下文适配器拟合用于检索问答的黑盒大语言模型
  • 网络状态的智能感知:WebKit 支持 Network Information API 深度解析
  • Vue3基础知识:组合式API中的provide和inject,他们作用是什么?如何使用?以及案例演示
  • Transformer自注意力机制(Self-Attention)模型
  • 【计算机体系结构】缓存的false sharing
  • Ubuntu24.04 Isaacgym的安装
  • docker 设置代理,通过代理服务器拉取镜像
  • OpenCV教程02:图像处理系统1.0(翻转+形态学+滤波+缩放+旋转)
  • 人工智能在招投标领域的运用---监控视频连续性检测
  • 加装德国进口高精度主轴 智能手机壳「高质量高效率」钻孔铣槽
  • Java Stream API 常用操作技巧