“创建近3000个独立的 QWidget 及其子控件。每个控件都拥有自己的窗口句柄、事件循环和绘制上下文,内存占用和绘制开销极其庞大“ 如何理解这句话?
① 关于“独立的窗口句柄” —— 部分正确,但致命
-
你的理解:每个
QWidget都有自己的HWND(或X11 Window)。 -
底层真相:确实如此。只要你设置
setAttribute(Qt::WA_NativeWindow)或让它成为顶层窗口(无父窗口),Qt会为它向操作系统申请一个独立的内核对象(Windows下是HWND,Linux下是XID)。 -
致命在哪:操作系统为每个窗口在内核非分页池中分配内存,且GDI句柄总数全局有限(Win10/11默认上限约65536个)。3000个窗口会瞬间吃掉近一半的系统句柄资源,导致其他软件(甚至任务管理器)绘制异常。
② 关于“独立的事件循环” —— 完全错误(这是最大的误解)
-
你的理解:每个控件拥有自己的事件循环(
QEventLoop)来处理自己的消息。 -
底层真相(极重要):
-
在Qt中,所有
QWidget必须且只能存活在GUI主线程(主线程)。 -
操作系统层:Windows的消息队列(
GetMessage/DispatchMessage)是线程级别的,而不是窗口级别的。整个进程的主线程只有一个消息队列。 -
Qt层:整个应用程序只有一个主事件循环(
QApplication::exec())。当鼠标点击窗口A时,操作系统把WM_LBUTTONDOWN投递到主线程的消息队列,Qt的QWindowsGuiEventDispatcher取出这个消息,根据HWND找到对应的QWidget对象指针,然后调用该对象的event()函数。
-
-
类比:操作系统是“总收发室”,所有窗口的信件(消息)都送到同一个收发室(主线程消息队列),收发员(Qt主循环)再按门牌号(HWND)分发给各家(窗口)。不存在每家自己设一个独立的收发室(独立循环)。
-
如果你强行在子线程创建
QWidget并跑QEventLoop,Qt会在create()系统调用时断言失败(ASSERT: "QWidget::create: Widgets must be created in the GUI thread"),程序直接崩溃。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐



所有评论(0)