目录
[1️. Qt::WA_TranslucentBackground](#1️. Qt::WA_TranslucentBackground)
[2️. Qt::WA_NoSystemBackground](#2️. Qt::WA_NoSystemBackground)
[和 Translucent 的区别](#和 Translucent 的区别)
[3️. Qt::WA_OpaquePaintEvent](#3️. Qt::WA_OpaquePaintEvent)
[4️. Qt::WA_TransparentForMouseEvents](#4️. Qt::WA_TransparentForMouseEvents)
[你的 Overlay 正确用法](#你的 Overlay 正确用法)
[5️. Qt::WA_Hover](#5️. Qt::WA_Hover)
[6️. Qt::WA_ShowWithoutActivating](#6️. Qt::WA_ShowWithoutActivating)
[7️. Qt::WA_DeleteOnClose](#7️. Qt::WA_DeleteOnClose)
[8️. Qt::WA_QuitOnClose](#8️. Qt::WA_QuitOnClose)
[9️. Qt::WA_NativeWindow/ WA_DontCreateNativeAncestors](#9️. Qt::WA_NativeWindow/ WA_DontCreateNativeAncestors)
[1️1. Qt::WA_PaintOnScreen](#1️1. Qt::WA_PaintOnScreen)
[六、X11 / Linux 专用(Windows 无效)](#六、X11 / Linux 专用(Windows 无效))
[MainWindow(Frameless + 透明圆角)](#MainWindow(Frameless + 透明圆角))
[视频 QLabel](#视频 QLabel)
[WindowControlOverlay(独立 Tool)](#WindowControlOverlay(独立 Tool))
觉得有用,就请您帮忙点赞转发收藏吧,您的鼓励是我创作的动力,多谢看官。
由于能力水平有限,文中的错误或不严谨的地方在所难免,还请批评指正。
Qt::WidgetAttribute是控制QWidget 内部行为、渲染机制、事件响应及生命周期的底层枚举,通过 setAttribute()设置,核心用于微调控件"如何工作"而非"长什么样"。常用的WidgetAttribute包含Qt::WA_DeleteOnClose/Qt::WA_TranslucentBackground/Qt::WA_NoSystemBackground/Qt::WA_TransparentForMouseEvents/Qt::WA_OpaquePaintEvent等
核心常用属性速查
Qt::WA_DeleteOnClose :窗口关闭时自动执行
deleteLater(),防止内存泄漏(严禁用于有父对象的窗口,否则会导致重复释放崩溃)。Qt::WA_TranslucentBackground :启用半透明背景(需配合
WA_NoSystemBackground及无边框标志FramelessWindowHint,且必须在show()前设置)。Qt::WA_NoSystemBackground:禁用系统默认背景绘制,用于自定义背景或实现透明效果。
Qt::WA_MouseTracking :启用鼠标追踪,使
mouseMoveEvent在无按键按下时也能触发(默认仅按下时触发)。Qt::WA_TransparentForMouseEvents:鼠标事件穿透,控件不接收任何鼠标事件,直接传递给下层控件(常用于遮罩层)。
Qt::WA_OpaquePaintEvent :标记为不透明绘制,Qt 跳过背景擦除步骤以提升性能(需确保
paintEvent绘制了完整区域,否则留残影)。Qt::WA_StaticContents:内容静态优化,调整大小时仅重绘新增区域,适用于 Logo、静态文本标签。
Qt::WA_ShowWithoutActivating:显示窗口但不激活(不抢占焦点),适用于悬浮提示、通知窗。
Qt::WA_AcceptDrops :允许接收拖放事件(通常直接调用
setAcceptDrops(true)即可)。Qt::WA_QuitOnClose :该窗口关闭时触发
QApplication::quit()退出程序(默认仅主窗口启用)。
一、先建立认知模型
Qt::WidgetAttribute不是"样式",而是给 Qt 内核 + 平台窗口系统 的 hint:
-
true= 启用该行为 / 覆盖默认 -
false= 恢复默认 -
很多属性 必须在
show()前设置 -
Windows / X11 / macOS 行为不完全一致
最容易被混淆的三组:
-
WA_TranslucentBackgroundvsWA_NoSystemBackground -
WA_OpaquePaintEventvsWA_NoSystemBackground -
WA_TransparentForMouseEventsvs 事件过滤
二、透明与背景绘制
1️. Qt::WA_TranslucentBackground
语义:这个 widget 要走 ARGB 合成,背景可以有 alpha。
setAttribute(Qt::WA_TranslucentBackground, true);
生效条件
-
顶级窗口
-
通常配合
Qt::FramelessWindowHint -
内部会自动设置
WA_NoSystemBackground -
Win7+ 需要 DWM(Aero)开启
行为
-
Qt 不再用 palette 刷背景
-
你必须自己
paintEvent画,或用子控件不透明背景兜底 -
不设背景 → 透桌面
典型场景
-
Frameless 圆角窗口
-
毛玻璃弹层
-
自定义标题栏 MainWindow
子控件不会自动继承"RGBA 透明",要逐层控制。
2️. Qt::WA_NoSystemBackground
语义 :paintEvent 前,不要让我擦系统默认背景(通常是灰/白)。
setAttribute(Qt::WA_NoSystemBackground, true);
和 Translucent 的区别
| 属性 | 跳过什么 | 是否支持 alpha |
|---|---|---|
| WA_NoSystemBackground | 系统主题背景填充 | ❌ 不支持 RGBA 透明 |
| WA_TranslucentBackground | 整个窗口走 ARGB | ✅ |
注意
-
开了不画背景 → 内容是"未定义像素"(可能残影)
-
Translucent 开启时 Qt 会自动补这个,但你手动再设一次也没问题
-
视频 QLabel 不要单独开这个而不开 Opaque,会闪
3️. Qt::WA_OpaquePaintEvent
语义 :我保证 paintEvent()里画满整个 widget 区域,Qt 别帮我清旧内容。
label->setAttribute(Qt::WA_OpaquePaintEvent, true);
适用
-
FFmpeg → QImage → QLabel / QWidget
-
D3D9 / OpenGL 渲染窗
-
每帧全区域重绘
不适用
-
半透明窗口(会和 Translucent 冲突)
-
局部重绘控件
视频 QLabel 的正确搭配:
ui->lblVideo->setAttribute(Qt::WA_OpaquePaintEvent, true);
ui->lblVideo->setStyleSheet("background:black;");
主窗口 Translucent,视频控件不透明,完美。
三、鼠标与事件相关
4️. Qt::WA_TransparentForMouseEvents
语义:鼠标事件直接穿透,不命中本 widget。
overlay->setAttribute(Qt::WA_TransparentForMouseEvents, true);
行为
-
不收
mousePress/Move/Release -
不抢焦点
-
下面 widget 收事件
-
Qt 内部仍可收
enter/leave(用来做 hover)
你的 Overlay 正确用法
-
整体穿透 (你要点按钮)
-
正确做法:不开这个 ,自己
mousePressEvent里判断按钮区 / 标题区 -
或:开这个 + 用
nativeEvent做 HTTRANSPARENT 局部穿透(高级)
5️. Qt::WA_Hover
setAttribute(Qt::WA_Hover, true);
-
不按鼠标也能收
QHoverEvent -
自定义按钮 / 标题栏图标必开
-
性能开销极小
6️. Qt::WA_ShowWithoutActivating
overlay->setAttribute(Qt::WA_ShowWithoutActivating, true);
-
show()不抢前台焦点 -
Taskbar 不闪
-
Tool / 音量条 / 字幕条必开
四、生命周期与窗口行为
7️. Qt::WA_DeleteOnClose
setAttribute(Qt::WA_DeleteOnClose, true);
-
close()后自动delete this -
只用于无父对象临时窗(关于框、设置窗)
-
有 parent 的别开,会 double free
8️. Qt::WA_QuitOnClose
-
默认只有最后一个普通窗口关了才 quit
-
播放器主窗必留,overlay(Tool)要关掉:
overlay->setAttribute(Qt::WA_QuitOnClose, false);
9️. Qt::WA_NativeWindow/ WA_DontCreateNativeAncestors
-
强制给 widget 建 WinId / HWND
-
D3D9 / DXVA / 原生子窗渲染前必用:
nativeChild->setAttribute(Qt::WA_NativeWindow, true);
auto hwnd = (HWND)nativeChild->winId();
五、绘制优化类
10.Qt::WA_StaticContents
-
resize 时只重绘"新露出来"的区域
-
左上对齐、内容不动的控件(图片查看器)
-
视频控件 别开(每帧都变)
1️1. Qt::WA_PaintOnScreen
-
跳过 Qt backing store,直接画 native
-
仅 X11 / 嵌入式有意义
-
Qt6 Windows + D3D 别碰
六、X11 / Linux 专用(Windows 无效)
-
WA_X11NetWmWindowTypeToolTip -
WA_X11NetWmWindowTypeNotification -
WA_X11BypassTransientForHint
→ 设置 EWMH atom,控制任务栏/合成器行为,桌面面板用。
七、播放器项目
MainWindow(Frameless + 透明圆角)
setWindowFlags(Qt::FramelessWindowHint | Qt::Window);
setAttribute(Qt::WA_TranslucentBackground, true);
centralWidget
cw->setStyleSheet("background:black;");
视频 QLabel
ui->lblVideo->setAttribute(Qt::WA_OpaquePaintEvent, true);
ui->lblVideo->setStyleSheet("background:black;");
WindowControlOverlay(独立 Tool)
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
setAttribute(Qt::WA_ShowWithoutActivating, true);
setAttribute(Qt::WA_TranslucentBackground, true);
// 不开 WA_TransparentForMouseEvents(要收点击)
八、一张速查表
| Attribute | true 含义 | 播放器用法 |
|---|---|---|
| WA_TranslucentBackground | ARGB 合成 | MainWindow |
| WA_NoSystemBackground | 不擦系统 bg | 自动被 Translucent 设 |
| WA_OpaquePaintEvent | paintEvent 画满 | 视频 Label |
| WA_TransparentForMouseEvents | 鼠标穿透 | overlay 别开 |
| WA_Hover | 收 hover | 按钮 |
| WA_ShowWithoutActivating | show 不抢焦点 | overlay |
| WA_DeleteOnClose | 关即删 | 临时窗 |
| WA_QuitOnClose | 关即退 App | overlay 关 |
| WA_NativeWindow | 强建 HWND | D3D 子窗 |
| WA_StaticContents | resize 局部重绘 | 视频 |
九、一句话总结
Translucent 管窗口合成,NoSystemBackground 管系统擦背景,OpaquePaintEvent 管每帧不擦旧图;三者不是替代关系,是三层不同责任。