Qt窗口混合编程:QWidget::createWindowContainer详解与实战
2026/9/10 5:39:14 网站建设 项目流程

说实话,我第一次在Qt源码里看到QWidget::createWindowContainer这个接口时,第一反应是"这玩意儿到底解决什么问题"。当时正在做一台上位机软件,客户要求把一个基于 Direct3D 渲染的第三方视频面板嵌进我们自己的 Qt 界面里。对面给的接口很简单:一个 HWND,你拿去显示吧。但问题来了,我们整个界面是 QWidget 体系,布局、样式、事件全都走 Qt 那一套,HWND 这种东西根本没法直接丢进 QVBoxLayout。

后来把 QWindow 和createWindowContainer折腾明白之后,才意识到这是 Qt 混合编程里一块非常关键但很少被讲透的拼图:它把底层的 QWindow 世界和上层的 QWidget 世界无缝桥接起来。这篇文章打算把这条桥的来龙去脉、实际用法和那些文档里不会细说的坑,一次讲清楚。

我默认看这篇文章的读者已经写过几个 QWidget 程序,但对 QWindow 还停留在"听说过"的阶段。我会从两种窗口体系为什么并存讲起,到最小可用示例,再到四类实操中必然踩中的坑,最后给几个进阶的嵌法。全程用实际代码和真实工程经验说话。

1. 为什么会有 QWidget 和 QWindow 两套体系,这决定了你什么时候需要 WindowContainer

要先搞清楚WindowContainer是干什么的,得先回到 Qt 的历史里看一眼。很多人只用 QWidget,从来没碰过 QWindow,但 Qt5 之后,Qt 的窗口系统实际上已经分裂成两层。

1.1 QWidget 是"老大哥",但它太重了

QWidget 是 Qt4 时代就存在的完整控件体系。一个 QWidget 实例不仅代表一个原生窗口,还承担了事件循环、布局管理、样式表、绘制系统、焦点管理这一整套上层建筑。好处是写业务界面非常快,拖几个控件、调调布局、连个信号槽,一个工具软件就出来了。

代价也在这:QWidget 太"重"了。它内部有一套完整的 QStyle、QPA 平台适配、双缓冲绘制逻辑,哪怕你只想创建一个最普通的空白窗口,背后也有大量对象在替你工作。而且 QWidget 跟底层原生窗口句柄(winId)之间的关系是"封装式"的,你想把一个外部的原生窗口、或者一个纯渲染窗口塞进 QWidget 的布局体系里,很难下手。

1.2 QWindow 是"轻量级接入点",但太简陋了

Qt5 为了支撑更底层的场景(OpenGL、Vulkan、Wayland、QML 场景图),引入了 QWindow。QWindow 只负责一件事:把"窗口"这个概念映射到操作系统级的原生窗口上。它没有布局系统、没有控件、没有样式表,但它可以直接创建原生窗口、接收底层事件、绑定渲染上下文。

拿 QML 举例,一个 QQuickWindow 本质上就是一个 QWindow 的子类。它的场景图渲染直接走硬件加速,根本不经过 QWidget 那套绘制管线。

问题随之而来:你在工程里可能会遇到一个QWindow(比如第三方库返回的、或者你用 QOpenGLWindow 子类化做的渲染窗口),而你的界面主体是 QWidget。它们俩一个是"原生窗口接入点",一个是"完整 UI 框架",不能互相addWidget。这时候就需要一个桥。

1.3 WindowContainer 就是那座桥

QWidget::createWindowContainer(QWindow*)这个静态函数,作用是:把一个 QWindow 包装成一个 QWidget,然后这个 QWidget 就能像普通控件一样放进布局、设置大小、挂到任意父控件上。容器内部的实现会替你把 QWindow 对应的原生窗口设置为该 QWidget 平台窗口的子窗口,并且同步坐标、尺寸、焦点等状态。

下面这个表基本上概括了两者的核心差异,也是我判断"该用哪套"的依据:

维度QWidgetQWindow
定位完整 UI 框架轻量窗口接入点
布局系统有(QLayout)
样式表
渲染方式CPU/GPU 混合绘制可直接绑定 OpenGL/Vulkan
原生窗口句柄通过 winId() 获取本身就是原生窗口
典型场景业务界面、对话框渲染窗口、QML、原生窗口桥接
能否直接 addWidget不能,需 createWindowContainer

所以,如果你的需求是"把一个 QWindow 放进 QWidget 界面里",不管这个 QWindow 是通过fromWinId包进来的外部窗口,还是自己写的QOpenGLWindow,Container 都是官方提供的那座桥。

2. WindowContainer 到底是怎么把 QWindow "塞进" QWidget 的,核心机制的拆解

光知道"这是个桥"还不够,要真正用好它,得明白桥墩子架在哪。我翻过 Qt 的源码,也写了不少测试代码验证行为,下面把createWindowContainer的运行机制拆开讲。

2.1 容器的本质:一个内部平台窗口的"养子"

从实现上看,createWindowContainer返回的 QWidget 并不是一个普通空控件,而是一个专门的QWindowContainerWidget。这个内部类做的事情,简单描述就是:

  • 在构造函数里,把传入的 QWindow 标记为容器窗口的"内嵌窗口"。
  • 当 Widget 被创建原生平台窗口时,会把內嵌 QWindow 的setParent指向容器 QWidget 的平台窗口。
  • QWindow 的几何位置、可见性会跟随 QWidget 的显示、隐藏、移动、缩放同步更新。

所以当你调用setWindow(QWindow*)之后,QWindow 在系统层面的父窗口句柄就被设置成了容器 Widget 的句柄。换句话说,从操作系统眼里看,这个 QWindow 是容器 Widget 的一个原生子窗口,而不是顶层窗口。

这里有个很关键的点:WindowContainer不会接管 QWindow 的渲染。子窗口的绘制完全由 QWindow 自己的渲染逻辑负责(OpenGL、D3D、场景图,随你)。Qt 只负责把它的"位置"和"大小"安顿好。

2.2 create()、winId、show 之间的时序关系

很多人第一次用 WindowContainer 失败,多半是栽在窗口创建的时序上。

QWindow 创建时并不会立刻创建对应的原生平台窗口。只有调用了create()show(),或者某些需要原生窗口的操作(比如获取 winId)才会真正触发底层创建。WindowContainer 内部会处理这个时序:当你调用createWindowContainer(qWindow)时,它不会立即创建,而是在容器 Widget 获取平台窗口(即winId()被调用或 Widget 显示)之后,才去创建/关联子窗口。

所以如果你把一个从未create()过的 QWindow 丢给 Container,它也能工作,Qt 会在合适的时候替你创建。但如果你想先对 QWindow 做一些设置(比如设置标志位、设置渲染上下文),就必须在传入 Container之前create()一次,否则有些平台设置不生效。

一个典型错误是:

QWindow *nativeWindow = new QWindow(); // 忘了调用 nativeWindow->create(); QWidget *container = QWidget::createWindowContainer(nativeWindow);

这种情况不是绝对崩溃,但我在 Windows 下遇到过若干奇奇怪怪的显示问题:子窗口不出来、大小不对、焦点丢失。后面我统一改成"先 create,再入容器"的写法,问题基本消失。

2.3 QWindow 与 QWidget 的事件、焦点、销毁交互

窗口被嵌入之后,鼠标点击、键盘输入这些事件怎么走?这是很多人的困惑。

实际上,点击发生在子窗口原生区域时,系统事件直接派发给子 QWindow,Qt 会把这个事件塞回 QWindow 的事件队列(QWindow 有独立的事件分发),不会变成容器 QWidget 的鼠标事件。这一点很重要,意味着你不能在容器 Widget 的mousePressEvent里收到来自子窗口区域的点击。

焦点管理同理。QWindow 有自己独立的focusObject概念。如果子窗口内嵌的是一个 QQuickWindow,它内部还有自己的焦点链。你需要手动决定何时把焦点给子窗口,比如重写容器 Widget 的focusInEvent来调用subWindow->requestActivate()

销毁顺序是我遇到过的第二大坑。Container 文档明确说了它不拥有 QWindow 的所有权。也就是说,你 new 一个 QWindow 传给 Container,Container 不会负责帮你 delete 它。如果 QWindow 被提前删除,容器里会留下一个悬空指针,一旦窗口重绘就会崩溃。

我建议的清理顺序是:

  1. 先从容器中移除 QWindow(调用container->setWindow(nullptr),或者直接删除容器)。
  2. 再删除 QWindow。
  3. 最后删除容器 Widget。

如果反过来先删 QWindow,Container 析构时会访问悬空指针,崩溃概率极高。

3. 最小可用示例:从建一个原生窗口到把它嵌入界面

下面给一个完整的例子,把"创建 QWindow -> 包成 QWidget -> 放到布局"这条链路跑通。我会用两种方式演示:第一种自己 new 一个 QWindow 做子窗口,第二种把系统级外部窗口句柄包进来。

3.1 方式一:自己创建 QWindow,然后嵌入

先写一个最简单的场景,界面左边放一个普通 QLabel,右边放一个由 QWindow 构成的"子窗口区域"。

// mainwindow.h #include <QMainWindow> #include <QWindow> class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: QWindow *m_subWindow = nullptr; QWidget *m_container = nullptr; };
// mainwindow.cpp #include "mainwindow.h" #include <QWindow> #include <QWidget> #include <QHBoxLayout> #include <QLabel> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setWindowTitle("WindowContainer 最小示例"); resize(800, 400); // 1. 先创建并配置 QWindow m_subWindow = new QWindow(); m_subWindow->setFlags(Qt::FramelessWindowHint | Qt::MSWindowsOwnDC); m_subWindow->create(); // 关键:先 create,再入容器 // 2. 用 WindowContainer 包住它 m_container = QWidget::createWindowContainer(m_subWindow); m_container->setMinimumSize(200, 200); // 3. 随便画点东西,方便观察子窗口区域 m_subWindow->setTitle("这是一个内嵌的 QWindow"); // 4. 布局 auto *layout = new QHBoxLayout(); layout->addWidget(new QLabel("左侧内容")); layout->addWidget(m_container, 1); auto *central = new QWidget(); central->setLayout(layout); setCentralWidget(central); } MainWindow::~MainWindow() { // 正确销毁顺序:先解除容器关联,再删 QWindow,最后删容器 if (m_container) { m_container->setWindow(nullptr); delete m_container; m_container = nullptr; } if (m_subWindow) { delete m_subWindow; m_subWindow = nullptr; } }

这个例子里,嵌入的 QWindow 是一个空白原生窗口,背景由系统决定,你基本看不清它内部有内容。所以为了让效果更直观,一般会用QOpenGLWindow或者QQuickWindow做子窗口,这样能看到有颜色的渲染内容。不过最小示例里先跑通结构最重要。

一个需要注意的点是Qt::MSWindowsOwnDC这个标志。如果你打算在子 QWindow 上做 GDI/GDI+ 绘制,加上这个标志可以让每个窗口拥有独立的 DC,避免切换画笔、画刷时互相污染。不加也能工作,但性能和多线程绘制时可能出问题。

3.2 方式二:用 fromWinId 嵌入外部原生窗口

这个才是真正的"杀手锏"。很多第三方库(工业相机 SDK、Halcon、播放器内核)只给你一个原生窗口句柄,你要做的就是把那个句柄"接进"你的 Qt 界面。

关键代码非常短:

// 假设 externalHwnd 是某个库返回的 HWND(Windows) QWindow *foreignWindow = QWindow::fromWinId(reinterpret_cast<WId>(externalHwnd)); foreignWindow->setFlags(Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus); QWidget *container = QWidget::createWindowContainer(foreignWindow); container->setMinimumSize(640, 480); ui->videoLayout->addWidget(container);

整个过程一句话总结:外部窗口句柄包装成 QWindow,QWindow 再用 WindowContainer 包成 QWidget。从此这个外部窗口就跟普通控件一样参与布局管理。

但我必须提醒一句血泪教训:fromWinId这种方式只能用于同一个进程内创建的窗口,跨进程是行不通的。道理很简单,Windows 的窗口归属与 message loop 绑定,你把另一个进程的 HWND 拿来 reparent 到自己的进程窗口下,消息派发、输入法、焦点都会乱套。跨进程的画面嵌入需要走 D3D 共享纹理、Desktop Duplication 那种路线,不要指望fromWinId能救你。

此外,fromWinId包装后的 QWindow 并不拥有原窗口的生命周期,外部库销毁它时,你的 QWindow 就成了一个悬空句柄。稳妥做法是同时捕获外部库的销毁回调,在回调里先从界面上移除容器再销毁 QWindow。

3.3 关于"父子生命周期"的归属问题

这里要专门展开讲一下所有权:createWindowContainer返回的 QWidget 拥有自己的生命周期,你把container加入布局后,布局接管了它的销毁,所以它一般不用手动 delete。但 QWindow 不是这样。

官方文档原文大意是:"The container does not take ownership of the window." 这直接导致了一个常见的反模式:

QWidget *widget = QWidget::createWindowContainer(new QWindow()); widget->show();

这段代码看着简洁,实际埋了雷。new 出来的 QWindow 没人删除,而且因为容器持有的是裸指针,当你关闭主窗口、容器销毁后,QWindow 并不会自动清理。如果 QWindow 内部还绑定了一个 OpenGL 上下文,那么上下文、缓冲、纹理这些 GPU 资源全部泄漏。

我见过的 Qt 程序里至少有四五个崩溃现场跟这种"匿名 new 一个 QWindow 丢给容器"的写法有关。

4. 实践中最容易踩的坑:焦点、缩放、销毁顺序与平台差异

把基础用法跑通之后,真正折磨人的是边缘场景。下面按我踩坑频率从高到低排列,逐个讲。

4.1 焦点问题:内嵌窗口抢焦点、不抢焦点

当内嵌 QWindow 被点击时,系统会把焦点给那个原生子窗口。这在大多数情况下是合理的,但在某些场景下会让你的主界面失焦。

举个例子,如果你的主窗口里有一个搜索框,用户正在输入关键词,然后不小心点了一下嵌在旁边的视频窗口,焦点立刻切到视频窗口,主窗口的搜索框光标消失。如果视频窗口本身压根不处理键盘输入,这个焦点切换就显得非常多余。

解决办法有两种,按场景选择:

  • 如果子窗口需要键盘输入(比如 QQuickWindow 里有 TextInput),那就在点击时主动requestActivate(),这是正常交互。
  • 如果子窗口只是纯展示,那就禁止它接收焦点。设置标志Qt::WindowDoesNotAcceptFocus是一个办法,但实测在个别平台上这个标志对子窗口不完全生效。

更可控的做法是重写容器的mousePressEvent,在子窗口区域点击时立刻把焦点抢回主窗口:

void MainWindow::onContainerClicked() { // 强制把焦点还给主窗体的某个控件 ui->searchEdit->setFocus(); }

如果你发现怎么也抢不回来,可以检查一下子窗口是否设置了Qt::WindowTransparentForInput,这个标志能让整个窗口完全忽略鼠标事件,但也会导致子窗口内部的交互全部失效。对纯展示没问题,如果子窗口需要响应点击就要慎重。

4.2 高 DPI 缩放:设备和像素坐标错位

从 Qt5.6、Qt6 开始高 DPI 是默认开启的。Container 内部会做"设备独立像素"到"物理像素"的换算,但问题是,第三方库的窗口不一定理解 Qt 的 DPI 缩放。

典型现象:在 150% 缩放的 Windows 显示器上,子窗口要么只显示一小块,要么溢出容器边界一大截。原因是外部库设置的窗口尺寸按物理像素算,而 Qt 布局给它的是逻辑像素尺寸,实际 setWindowPos 时可能没有乘上 devicePixelRatio,也可能乘了。

我在工程里采用的最直接的规避法是:设置进程级别的 DPI 感知,让 Qt 自己处理缩放,第三方窗口那边不用额外的物理像素换算。

// main.cpp #include <QApplication> int main(int argc, char *argv[]) { // Windows 下让系统 DPI 感知交给 Qt QApplication::setHighDpiScaleFactorRoundingPolicy( Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); QApplication app(argc, argv); // ... return app.exec(); }

如果你使用 Qt6,高 DPI 默认开启,PassThrough策略可以让缩放比例不那么"四舍五入",子窗口尺寸更贴近外部库的真实尺寸。另外,当系统缩放比例变化(比如把窗口从 100% 的屏幕拖到 150% 的屏幕)时,QWindow::devicePixelRatioChanged会触发,但你没法控制外部库的行为,所以实测中偶尔会出现子窗口闪烁、短暂错位。缓解办法是尽量让外部库窗口保持"无边框 + 强制跟随容器大小",而不是外部库自己管理尺寸。

4.3 销毁顺序与崩溃:谁先死的问题

我在前面已经提过销毁顺序,这里单独列出来是因为它真的太容易爆了,而且爆的时机不在现场,往往出现在用户关闭窗口后的几秒内,或者下一次打开界面时。

崩溃的机理是这样的:QWindowContainerWidget在析构时会访问它关联的 QWindow 指针,如果此时该指针已经指向被释放的内存,轻则野指针访问,重则整段程序段错误。

推荐的安全模式是:

  1. 用一个 QPointer 保存子窗口。
  2. 窗口关闭或界面销毁时,先确认 QWindow 存在,调用container->setWindow(nullptr)解除关联。
  3. 再删除 QWindow。
  4. 最后删除容器。
QPointer<QWindow> m_subWindow; void closeVideoPanel() { if (m_container) { m_container->setWindow(nullptr); } if (m_subWindow) { delete m_subWindow; // 正常析构 } delete m_container; m_container = nullptr; }

用 QPointer 还有一个额外好处:如果外部库偷偷帮你把 QWindow 删了,QPointer 会自动置空,后续判断就不会碰悬空指针。虽然不能 100% 防止所有崩溃,但能挡住大部分。

4.4 不同平台的"宽容度"差异

我分别在 Windows、macOS、Linux 上跑过同一套 Container 代码,差异非常明显。

  • Windows:兼容性最好。只要进程内窗口,基本都能嵌进去,子窗口遮挡、层级、焦点也都还算听话。
  • Linux X11:可以用,但取决于窗口管理器。有些 WM 对 override-redirect 窗口处理不太好,出现子窗口不跟随移动或者留残影的情况。
  • Linux Wayland:这个平台是最大的坑。Wayland 协议本身上不允许客户端随意重设父子窗口关系或者说子窗口嵌入,Container 在 Wayland 下的能力非常有限。如果你的客户环境是纯 Wayland,不要承诺"窗口嵌入"功能,老老实实换成共用共享内存纹理或者走 XWayland 兼容层。
  • macOS:原生窗口嵌入做得还行,但限制也明显:子窗口无法做到真正的透明叠加,某些 NSView 层级里的特殊绘制也可能出现渲染内容不显示。

所以在项目早期做技术选型时,一定要先确认目标平台的限制,否则后面返工成本很高。

5. 进阶玩法:嵌入 QQuickWindow、D3D 面板和第三方 App 窗口

基础用法稳定之后,可以把思路再打开一些。WindowContainer 不是只能嵌一个空白 QWindow,很多"不太像 QWidget 界面的东西"都能通过它融进你的界面。

5.1 把 QML 界面嵌进 QWidget 程序

QML 的渲染核心是QQuickWindow,而QQuickWindow继承自QWindow,所以一个自然的推论就是:用createWindowContainer把一个QQuickWindow包起来,塞进 QWidget 界面。

不过实际工程里,更推荐用QQuickWidget,因为它本身就继承自 QWidget,且内部做了不少 Container 场景的优化。但QQuickWidget跟纯渲染场景有一个差异:它走的是 Texture 合成,所有渲染内容会先被画到纹理再合成到 QWidget 上,这跟 Container 的"独立原生子窗口"模式不一样。

什么时候必须用 Container 而不是 QQuickWidget?当你的 QML 窗口需要独立的原生窗口做叠加、弹层、多屏显示时。举个例子,如果你在 QML 里用了一个Window { flags: Qt.WindowStaysOnTopHint }弹层,用 QQuickWidget 在某些平台确实没法触发原生弹层,而 Container 包装的 QQuickWindow 则可以完整保留 QML 的窗口管理能力。

写法上,创建 QQuickWindow 并让其渲染到子窗口,然后再包 Container:

QQmlEngine *engine = new QQmlEngine(this); QQmlComponent component(engine, QUrl("qrc:/SubPanel.qml")); QQuickWindow *quickWindow = qobject_cast<QQuickWindow*>(component.create()); QWidget *container = QWidget::createWindowContainer(quickWindow); container->setMinimumSize(320, 240); layout->addWidget(container);

这种方式比 QQuickWidget 重,但有时候真的更好用。

5.2 嵌入第三方 Direct3D / OpenGL 渲染窗口

开头场景里,我接的第三方视频面板就是这种类型。这类库通常要求你传入一个HWND或者WId作为渲染目标,并且这个窗口的渲染由库自己的渲染线程完成。

实践中的操作链路非常清晰:

  1. new QWindow()创建空白原生子窗口,作为第三方库的渲染目标。
  2. 获取它的winId(),传给第三方库初始化。
  3. createWindowContainer把子窗口包成 QWidget 放进布局。
  4. 第三方库往这个 HWND 上渲染画面。

这比fromWinId更安全,因为createWindowContainer的子窗口生命周期完全由你管理,不会出现外部库先销毁句柄导致悬空指针的问题。

一个典型的组态软件场景是:界面用 QWidget 搭好框架,中间有一块区域显示第三方渲染的三维模型或视频流。这个区域就是一个 Container,内嵌一个专门给渲染库用的 QWindow。随着容器尺寸变化,Qt 会自动调整子窗口大小,渲染库那边只要从事件循环拿出一帧画面画上去即可。

5.3 反向混合:QML 里嵌入 QWidget

既然能把 QWindow 往 QWidget 里塞,那反过来能不能在 QML 里放 QWidget?答案是:不推荐直接用 Container 反向做。

QML 程序的主体是 QQuickWindow,它是 QWindow 体系,而 QWidget 体系里的控件不能直接挂到 QQuickWindow 下。官方提供的QQuickWidget是把 QML 放进 QWidget,至于把 QWidget 放进 QML,通常是靠QQuickPaintedItem包装某个 QWidget 的图像纹理,或者干脆反过来:整个界面用 QWidget 搭,局部区域用 Container 嵌 QQuickWindow。

我自己的经验是:除非你真的需要在一个 QML 界面的某个固定位置放一个纯 QWidget 控件(比如某个老旧的第三方控件,它只能实例化为 QWidget),否则别折腾。混合编程的优先级应该是:

  • 尽量统一到一套体系(要么 QWidget,要么 QML)。
  • 实在避不开,优先用QQuickWidget(QML 塞 Widget)。
  • 嵌入原生渲染窗口或外部句柄,才考虑 Container。
  • 反向把 QWidget 塞 QML,是最后手段。

5.4 跟"Qt 中消息队列"常见问题的关系

既然你是混合编程新手,可能已经在 Qt 的群里看到过"qcoreapplication::exec() 之后就无法捕获了"这类问题。这其实跟 Container 关系不大,但混合编程经常会触发类似困惑。

QWindow 的事件派发走的是它自己的QWindowSystemInterface,跟 QWidget 的事件系统有一部分重叠但又不完全相同。当你在 QML 或原生子窗口里做一些耗时操作阻塞了消息循环,确实会导致父 QWidget 的刷新和鼠标事件卡住。这跟"Container 不处理子窗口渲染"是一个道理:子窗口的消息循环和父窗口的消息循环都跑在同一个 QCoreApplication 事件循环里,一旦有一个阻塞,所有窗口全部假死。

所以做混合编程,记住一个铁律:不要在 UI 线程里做耗时操作。尤其是第三方渲染库如果提供了独立的渲染线程,千万别把它挪到主线程里跑。

写在实操之后的小结

现在再把所有代码和踩坑经验浓缩成几条我自己都在用的固定套路:

第一,先确认"你需要嵌入的东西"是不是一个 QWindow。如果不是,想办法把它转成 QWindow(比如fromWinId);如果是,直接createWindowContainer即可。

第二,创建子窗口后,优先显式create()一次,避免平台窗口在 Container 内部延迟创建导致的各种时序问题。

第三,生命周期管理上,永远把 QWindow 当成"你借给 Container 的东西",而不是"Container 替你保管的东西"。销毁时先解除关联再删 QWindow,不会错。

第四,多平台发布前一定要在每个目标平台上跑一遍嵌入、缩放、焦点、销毁这四个场景,别只在一台 Windows 上测完就发版。

第五,如果嵌的是第三方库窗口,提前确认它的窗口消息模型、DPI 感知模式和线程模型。这三点决定了你的嵌入方案能不能长期稳定运行。

Qt 混合编程这条路分支很多,WindowContainer只是其中一道桥。希望这篇把桥的结构、桥墩和能过什么车都讲清楚了,你下次再遇到"QWidget 和 QWindow 必须共存"的需求时,能少走几条弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询