简介:KDDockWidgets是Qt生态中功能完善的可停靠窗口(Docking)组件,这套资源为基于VS2019与Qt5.15.2(64位)预编译的动态库和完整源码,面向需要在Qt Quick或Widgets应用中实现灵活窗口停靠布局的开发者。整个压缩包为RAR格式,共956个文件,约51.56MB,其中包含279个头文件、139个C++源文件、12个DLL动态库及配套LIB/EXE产物,还有QML界面资源、JSON配置、CMake脚本与PDF说明文档等,便于按需查阅和二次开发。需要特别留意,动态库严格区分为Quick和QWidget两种版本,对应include头文件不能混用,并且仅支持64位编译环境,32位工程不可使用。资源内附带两个演示demo,每个demo均包含KDDockWidgets工程文件夹,开发者可直接将KDDockWidgets.pri引入自己的项目,省去复杂配置,也能对照示例快速掌握集成方法与布局效果。目前已有789人学习下载,配合作者博客中的讲解,可更深入地理解停靠窗口的集成细节和常见问题。
1. VS2019 编译 KDDockWidgets 这件事,卡住过很多人
在 Windows 桌面端做多窗口应用,绕不开“停靠布局”这套交互:侧边栏可以拖出来、贴回去、Tab 合并,外观像 Visual Studio 自己的面板。自己写一套能商用的停靠框架,少说两到三个月,而且拖拽、吸附、布局保存这些细节特别容易烂尾。KDDockWidgets 就是专门解决这个问题的开源库,底层基于 Qt,性能与交互都贴近生产级。但这个库不直接给 VS 用户发编译好的二进制,官方默认只给 QMake/CMake 的源码工程,导致大量开发者卡在“源码在手,编不出 dll”这一步——Qt 版本不对、CMake 找不到 Qt、编译器工具集不匹配,任何一个环节都能让编译失败。这篇笔记的目标就一个:把 KDDockWidgets 在 VS2019 下的编译链路、动态库产物和集成步骤一次讲透,照着能产出 KDDockWidgets.dll,并能被自己的 Qt 工程正常加载。
2. KDDockWidgets 是什么:为什么值得先花半小时理解它的源码结构
2.1 停靠框架要解决的核心问题
停靠框架(Docking System)做的事情是:把一个窗口区域抽象成可停靠的 DockWidget,用户可以拖动它到主窗口的上下左右边缘,也可以让它浮动成独立窗口,还可以多个 DockWidget 叠成 Tab 页。KDDockWidgets 的核心卖点是“用 Qt 标准控件实现,不依赖第三方重量级组件”,而且它把 MainWindow、DropArea、DockWidget 这几个类拆得很清楚,改行为比 QMdiArea 和 QDockWidget 默认形态灵活得多。
选 KDDockWidgets 而不是 QDockWidget,主要是因为 QDockWidget 的浮动窗口和布局恢复能力比较弱,拖动反馈也粗糙。KDDockWidgets 支持多窗口间互相拖拽停靠,这在 Qt 原生控件里是做不到的。另外它的 License 是 LGPL,动态链接的情况下可以闭源商用,这也是很多团队选它的关键原因。
2.2 源码目录里藏着的“三件套”:core、dockwidget、multisplitter
从 GitHub 拉下来的 KDDockWidgets 源码,顶层目录基本是 examples、src、tests 这三个。src 下面要盯住几个子目录:Core 是核心逻辑(拖拽、状态管理),DockWidget 是各个 Dock 组件,MultiSplitter 是停靠区域的布局算法。编译之前最好先把 MultiSplitter 这个目录翻一下,里面是窗口分割的几何计算,后续你要是想改“最小停靠宽度”“浮动窗口透明度”这类行为,改的就是这里。
源码根目录的 CMakeLists.txt 是整个工程的入口,它通过add_subdirectory把 Core、DockWidget 等模块组装起来。VS2019 编译走 CMake 是最稳的路径,因为 KDDockWidgets 对 qmake 的支持虽然还在,但新特性基本都优先落在 CMake 上。
2.3 动态库与静态库的选择:不是越多越好
编译 KDDockWidgets 时,CMake 会产出一组库文件,包括核心库 KDDockWidgets(或带 Qt 主版本后缀的 KDDockWidgets_Qt6、KDDockWidgets_Qt5),如果你打开的是多窗口示例,还会编出 KDDockWidgets 的 examples 可执行文件。选择动态库而不是静态库,最直接的好处是:主程序体积小,KDDockWidgets 的 bug 修复后只要替换 dll 就能生效,不用重新链接整个 exe。
动态库的代价是部署时要多带一个 dll,还要保证 Qt 的运行库(Qt6Core.dll、Qt6Gui.dll、Qt6Widgets.dll)路径能被找到。你要是图省事选静态库,编译时间会更长,而且链接时经常遇到“符号重定义”之类的问题,反而更难排查。所以我的建议是:项目发布用动态库,调试阶段也保持动态库,保持开发与生产环境一致。
3. 从源码到 dll:用 CMake 在 VS2019 下产出 KDDockWidgets 动态库
3.1 环境准备:确认三样东西,缺一不可
开始编译前,先把环境清单过一遍。第一是 Visual Studio 2019,必须安装“使用 C++ 的桌面开发”工作负载,里面包含 MSVC v142 工具集和 Windows SDK。第二是 CMake,VS2019 自带 CMake 组件,也可以用 cmake.org 的独立安装包,版本建议 3.16 以上。第三是 Qt,KDDockWidgets 依赖 Qt5 或 Qt6,编译前必须用 Qt 官方安装器装好对应版本的 MSVC 2019 64-bit 组件。
特别要注意 Qt 的编译器必须与 VS2019 匹配:VS2019 对应 MSVC v142,Qt 安装器里要选 “MSVC 2019 64-bit” 那一套,不能选 MinGW 版本。我见过不少人在这一步翻车,Qt 装的是 MinGW,结果 VS2019 的 CMake 配置阶段就报 “Could NOT find Qt6”,因为两者的 ABI 完全不兼容。
3.2 CMake 配置:核心命令与参数清单
打开“x64 Native Tools Command Prompt for VS2019”(开始菜单里搜这个名字),先确认 CMake 和 Qt 的环境变量。然后进入源码目录,执行以下命令:
mkdir build-vs2019 cd build-vs2019 cmake .. -G "Visual Studio 16 2019" -A x64 ^ -DCMAKE_PREFIX_PATH=C:/Qt/6.5.3/msvc2019_64 ^ -DCMAKE_BUILD_TYPE=Release ^ -DCMAKE_INSTALL_PREFIX=C:/kddockwidgets-install ^ -DKDDockWidgets_EXAMPLES=ON这里-G "Visual Studio 16 2019"指定生成 VS2019 工程;-A x64指定 64 位架构,如果你的目标平台是 x86,可以改成 Win32,但不建议,Qt 官方发布的预编译库基本都是 64 位为主。CMAKE_PREFIX_PATH指向 Qt 的安装目录,CMake 会在这里找 Qt6Config.cmake 之类的配置文件。KDDockWidgets_EXAMPLES打开示例工程,建议第一次编译时打开,编译完可以直接跑 examples 验证动态库是否正常。
如果 CMake 报错找不到 Qt,不要急着怀疑路径,先检查C:/Qt/6.5.3/msvc2019_64/lib/cmake目录是否存在,再确认 CMAKE_PREFIX_PATH 写的是否是这个路径的父目录。另外,CMake 缓存会记住第一次配置的结果,改路径后需要删掉 build 目录重来,否则会继续用旧缓存报同样的错。
3.3 编译与产物检查:三个关键文件
配置成功后,执行编译命令。用 CMake 生成 VS 工程后,也可以用 Visual Studio 直接打开 build-vs2019 目录下的 KDDockWidgets.sln,在“解决方案配置”里切到 Release/x64,右键 KDDockWidgets 项目选择“生成”。命令行方式更可控:
cmake --build . --config Release --parallel 8--config Release指定 Release 配置,--parallel 8表示 8 线程并行编译,第一次编译会比较久,耐心等它跑完。编译完成后,去build-vs2019/src/Release目录检查产物,正常会有 KDDockWidgets.dll 和 KDDockWidgets.lib,如果你用的是 Qt6,还会见到 KDDockWidgets_Qt6.dll 这样带版本尾巴的库名。同时 examples/Release 下会有多个示例 exe,随便挑一个运行,比如最简单的 HelloWorld,能看到窗口出现并且能拖动侧边栏,就说明动态库本身没有问题。
3.4 安装到本地:省去手动拷 dll 的麻烦
cmake --install . --config Release这条命令会把头文件、dll、lib、cmake 配置文件统一安装到 CMAKE_INSTALL_PREFIX 指定的目录。安装后的目录结构大概是这样:include/KDDockWidgets 下是头文件,bin 下是 dll,lib 下是导入库,lib/cmake 下是 KDDockWidgetsConfig.cmake。你后续自己的工程只要通过 find_package(KDDockWidgets) 就能接上,不用再手动配置头文件路径和库路径。
4. 把动态库接进你自己的 VS2019 Qt 工程:两种链接方式
4.1 隐式链接:最常规的做法
假设你自己有一个 Qt Widgets 工程,工程文件是 .vcxproj。在项目属性里需要设置几个地方:C/C++ → 常规 → 附加包含目录,加上C:/kddockwidgets-install/include;链接器 → 常规 → 附加库目录,加上C:/kddockwidgets-install/lib;链接器 → 输入 → 附加依赖项,写上KDDockWidgets.lib(Qt6 对应 KDDockWidgets_Qt6.lib)。
如果你用 CMake 管理自己的工程,代码里只需要三行:
find_package(KDDockWidgets REQUIRED) target_link_libraries(your_app PRIVATE KDDockWidgets::kddockwidgets)这是最省心的方式,KDDockWidgets 安装时已经导出了 CMake 的 package 配置,find_package会把头文件目录、导入库、依赖的 Qt 模块一次性带全。注意你的工程里的 Qt 版本要和编译 KDDockWidgets 时用的一致,混用 Qt5 编译的库和 Qt6 工程,链接时会出现一堆 “unresolved external symbol”。
4.2 使用 KDDockWidgets 的 API:最小可运行代码
动态库链接成功后,写一段最小代码验证:
#include <QApplication> #include <KDDockWidgets/MainWindow.h> #include <KDDockWidgets/DockWidget.h> int main(int argc, char** argv) { QApplication app(argc, argv); KDDockWidgets::MainWindow window; window.resize(1024, 768); auto* dock = new KDDockWidgets::DockWidget("Sidebar"); dock->setWidget(new QTextEdit(&window)); window.addDockWidgetAsTab(dock); window.show(); return app.exec(); }这段代码创建了一个主窗口,把一个 DockWidget 以 Tab 页的形式加进去。addDockWidgetAsTab是最简单的停靠方式,适合做第一个验证程序;KDDockWidgets 还提供addDockWidgetAsSidePanel让面板停靠在侧边,以及多个 DockWidget 之间的位置管理接口,但先跑通这个最小例子,比一上来就搞复杂布局稳妥得多。
4.3 运行时找不到 dll 的排查顺序
程序编译通过但运行时报 “无法启动此程序,因为计算机中丢失 KDDockWidgets.dll”,这是最常见的问题。排查顺序是:第一,把 KDDockWidgets.dll 拷贝到 exe 同目录;第二,确认 Qt 的 dll(Qt6Core.dll 等)也在 exe 同目录或系统 PATH 里;第三,如果还报错,用 Dependency Walker 或 Visual Studio 的“调试 → 窗口 → 模块”看具体缺哪个依赖。
补充一点:Qt 的插件(如 platforms/qwindows.dll)也要能被找到。如果你的 exe 目录下没有 platforms 文件夹,Qt 程序启动时会直接崩溃,这个和 KDDockWidgets 本身无关,但经常被误认为是动态库有问题。用 windeployqt 工具可以自动把 Qt 运行库和插件拷贝到 exe 目录,省去手工搬运。
5. 动态库与源码的避坑清单:五条血泪经验
5.1 Debug 与 Release 混用导致的内存崩溃
现象:用 Release 版 KDDockWidgets.dll 链接 Debug 版自己的工程,程序运行时随机崩溃,有时是中文乱码,有时是 QByteArray 内部断言失败。
原因:Qt 的 Debug 和 Release 使用不同的内存分配器和数据结构布局,两个版本的 Qt 核心库混在一起时,对象在 Release 库中创建、在 Debug 库中释放,直接踩到堆损坏。
解决:KDDockWidgets 的库版本必须和你的工程一致。你的工程是 Debug 配置,就必须用cmake --build . --config Debug编出来的 KDDockWidgetsd.dll(注意名字里的 d)。链接库也要对应,Debug 工程链接 KDDockWidgetsd.lib,Release 工程链接 KDDockWidgets.lib。
5.2 源码更新后 dll 没重新编译,界面出现“新接口找不到”
现象:刚拉取最新源码编译的 dll 替换到部署目录后,程序启动报错找不到某个符号,或者点击某功能时直接崩溃。
原因:KDDockWidgets 的源码更新频繁,接口或类布局可能有变动,旧 exe 链接的是旧版动态库,导入表里的符号地址已经失效。
解决:本地源码更新后,不要只编译 dll 替换,要把自己工程的 exe 也重新编译一遍。如果你用隐式链接,exe 和 dll 必须同时更新,这是 Windows 动态链接的常识,但在快速迭代时最容易疏忽。
5.3 CMake 找不到 Qt,但 Qt 明明装了
现象:CMake 配置时输出Could NOT find Qt6,检查 Qt 路径确实存在。
原因:CMAKE_PREFIX_PATH 只给到了 Qt 的安装根目录,但 CMake 需要的是C:/Qt/6.5.3/msvc2019_64这个包含 lib/cmake 的目录;或者把 Qt 安装成了 MinGW 版本,MSVC 的 CMake 工程找不到对应的配置。
解决:确认路径指向 Qt 对应编译器版本的根目录,同时打开C:/Qt/6.5.3/msvc2019_64/lib/cmake看是否存在 Qt6Config.cmake 这一类文件。如果存在但 CMake 仍报错,在 build 目录里删掉 CMakeCache.txt 重新配置,不要复用旧缓存。
5.4 编译成功但示例程序启动白屏
现象:KDDockWidgets 的 examples 编译通过,运行后主窗口出现了,但内容是空白的,或者所有 DockWidget 都不显示。
原因:最常见的不是 KDDockWidgets 的问题,而是 Qt 插件目录没有被识别。exe 在 build 目录下运行时,Qt 找不到 platforms 插件。
解决:在 Qt 安装目录下找到C:/Qt/6.5.3/msvc2019_64/plugins/platforms,把它整个拷贝到 exe 同目录下,或者用 windeployqt 工具自动部署。之后再运行,窗口内容就正常了。
5.5 动态库文件拷贝不全,部署到别的机器报错
现象:把 exe 和 KDDockWidgets.dll 拷到一台没装 Qt 的电脑上运行,双击没反应,事件查看器里显示找不到 Qt6Core.dll。
原因:KDDockWidgets.dll 依赖 Qt 运行库,Qt 运行库又依赖 C++ 运行库,单纯拷贝一个 dll 是不够的。
解决:不要手动挑 dll 拷贝,用 Qt 自带的 windeployqt 命令。在 VS2019 的开发者命令行里执行windeployqt your_app.exe,它会自动把 Qt 的 dll、插件、翻译文件全部拷到 exe 目录,基本不会漏。
6. 进阶:用 KDDockWidgets 的调试日志验证动态库是否真的工作
这个技巧对排查“dll 编好了但拖拽行为异常”特别有效。KDDockWidgets 内部预留了日志开关,不需要改源码,在程序启动前设置一个环境变量就能打开详细输出:
set KDDOCKWIDGETS_LOG_LEVEL=debug然后在你的程序里加上一段代码,把日志打印到控制台:
#include <QDebug> #include <spdlog/spdlog.h> int main(int argc, char** argv) { qputenv("KDDOCKWIDGETS_LOG_LEVEL", "debug"); spdlog::set_level(spdlog::level::debug); // 你的业务代码 }设置这个环境变量后,KDDockWidgets 会输出拖拽事件、布局计算、窗口停靠的详细信息。比如拖一个 DockWidget 到边缘时,日志里会显示DropArea::onDrop这样的关键字;如果某次停靠失败,日志里通常能看到Invalid drop position一类的提示。这个日志对确认“到底是动态库行为异常,还是我的业务代码传参有误”非常有用。
我自己的习惯是:每次更新 KDDockWidgets 源码重新编译后,先用 examples 跑一遍,再打开日志跑一遍自己的工程,最后才替换到正式分支。这样虽然多花几分钟,但能提前过滤掉大部分“编译成功但运行行为不对”的坑。KDDockWidgets 这个库整体质量不错,只要 Qt 版本、MSVC 工具集和 Debug/Release 这三组参数对齐,VS2019 下编出可用的动态库并不难,希望这些经验能帮你少走几步弯路。
本文还有配套的精品资源,点击获取