“引言:告别死板的固定布局!使用QDockWidget来赋予用户自定义工作区的自由,通过可停靠、可浮动的面板,极大地提升应用的专业性和用户体验。”

大家好,欢迎来到Qt的“专业布局”工坊!
你是否曾惊叹于那些专业软件(如IDE、3D建模软件、音视频编辑器)界面的灵活性?
-
你可以将“项目浏览器”面板从左边 拖拽 到右边。
-
你可以将“输出”面板 浮动 成一个独立的窗口。
-
你甚至可以将“属性”面板和“层级”面板 堆叠 成一个带标签页的组合。
这种高度可定制的界面,是如何实现的?答案就藏在 QMainWindow 的一个“最佳拍档”里—— QDockWidget (可停靠窗口部件) 。
今天,我们用纯粹的C++代码,从零开始,搭建一个拥有专业级可定制化布局的应用程序框架!
第一章: QDockWidget 是什么?
QDockWidget 本质上是一个特殊的 容器 ,你可以把它想象成一个带有“ 磁性把手 ”的 QWidget 。
-
容器 :你可以像使用普通
QWidget一样,往QDockWidget的内部放置 任何 控件和布局(列如一个QListWidget作为项目树)。 -
磁性把手 :这个“把手”就是它的标题栏。用户可以通过拖动这个标题栏,来完成一系列神奇的操作:
-
停靠 (Docking) :将它“吸附”到主窗口的上、下、左、右四个停靠区。
-
浮动 (Floating) :将它从主窗口中“拽”出来,变成一个独立的、顶层的窗口。
-
组合 (Stacking) :将多个
QDockWidget拖拽到同一个区域,它们会自动合并成一个带有标签页的组合面板。
核心前提 : QDockWidget 只能 在 QMainWindow 中使用。 QMainWindow 天生就为它划分好了“停靠区域”,并管理着所有停靠和浮动的复杂逻辑。
第二章:实战演练:纯代码搭建迷你IDE框架
我们的目标是创建一个类似简化版IDE的主窗口,它包含:
-
一个 中央编辑区 (
QTextEdit)。 -
一个可停靠在左侧的 “项目浏览器” 面板 (
QTreeWidget)。 -
一个可停靠在底部的 “编译输出” 面板 (
QListWidget)。 -
一个与“编译输出” 组合成标签页 的 “问题列表” 面板。
第一步:创建主窗口类
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
// 前向声明
classQTextEdit;
classQDockWidget;
classMainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent =ptr);
~MainWindow;
private:
voidcreateDocks; // 创建所有DockWidget的函数
voidsetupMenus; // 设置菜单栏的函数
QTextEdit *m_editor; // 中心控件
};
#endif // MAINWINDOW_H
第二步:实现主窗口的搭建
mainwindow.cpp
#include "mainwindow.h"
#include
#include
#include
#include
#include
#include
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setWindowTitle(u8"纯代码DockWidget演示");
resize(1000,700);
// 1. 设置中心控件
m_editor = newQTextEdit(this);
m_editor->setText(u8"这里是主编辑区...");
setCentralWidget(m_editor);
// 2. 调用函数创建所有的Dock
createDocks;
// 3. 允许DockWidget嵌套组合
setDockNestingEnabled(true);
}
MainWindow::~MainWindow
{
}
voidMainWindow::createDocks
{
// --- a. 创建左侧的“项目浏览器” ---
QDockWidget *projectDock = newQDockWidget(u8"项目浏览器", this);
QTreeWidget *projectTree = newQTreeWidget(projectDock);
projectTree->setHeaderHidden(true);
newQTreeWidgetItem(projectTree, {"main.cpp"});
newQTreeWidgetItem(projectTree, {"mainwindow.h"});
newQTreeWidgetItem(projectTree, {"mainwindow.cpp"});
projectDock->setWidget(projectTree);
// 将其添加到主窗口的左侧停靠区
addDockWidget(Qt::LeftDockWidgetArea, projectDock);
// --- b. 创建底部的“编译输出” ---
QDockWidget *outputDock = newQDockWidget(u8"编译输出", this);
QListWidget *outputList = newQListWidget(outputDock);
outputList->addItems({u8"编译开始...", u8"链接...", u8"编译成功!"});
outputDock->setWidget(outputList);
addDockWidget(Qt::BottomDockWidgetArea, outputDock);
// --- c. 创建另一个底部面板“问题列表” ---
QDockWidget *issuesDock = newQDockWidget(u8"问题列表", this);
QListWidget *issuesList = newQListWidget(issuesDock);
issuesList->addItems({u8"警告: 未使用的变量 'x'", u8"警告: 隐式类型转换"});
issuesDock->setWidget(issuesList);
addDockWidget(Qt::BottomDockWidgetArea, issuesDock);
// --- d. (关键) 将“问题列表”与“编译输出”组合成标签页 ---
// 这个函数会将第一个参数的DockWidget堆叠在第二个之上
tabifyDockWidget(outputDock, issuesDock);
// 让“编译输出”默认被选中
outputDock->raise;
// --- e. 在“视图”菜单中添加控制项 ---
QMenu *viewMenu = menuBar->addMenu(u8"视图");
viewMenu->addAction(projectDock->toggleViewAction);
viewMenu->addAction(outputDock->toggleViewAction);
viewMenu->addAction(issuesDock->toggleViewAction);
}
main.cpp
#include "mainwindow.h"
#include
intmain(intargc,char*argv[])
{
QApplicationa(argc, argv);
MainWindow w;
w.show;
return a.exec;
}
运行你的程序! 一个完全由代码构建的、功能完备的IDE框架就诞生了!
-
你可以自由地拖动左侧和底部的面板。
-
底部的“编译输出”和“问题列表”已经自动合并成了标签页,你可以点击切换。
-
你可以将任何面板拖出,使其浮动。
-
你可以将“项目浏览器”拖到右侧,甚至拖到下方的标签页组合中!
-
通过顶部的“视图”菜单,你可以方便地显示或隐藏任何一个面板。

第三章:保存与恢复布局
一个专业应用,应该能记住用户上次关闭时精心调整的面板布局。 QMainWindow 提供了两个神奇的函数来实现这一点,我们可以结合 QSettings 来使用。
1. 在 mainwindow.h 中添加
#include
// ...
protected:
voidcloseEvent(QCloseEvent *event) override;
2. 在 mainwindow.cpp 中实现
#include
#include
// 在构造函数的末尾添加
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// ... (之前的代码) ...
// 尝试恢复布局
QSettingssettings("MyCompany", "MyApp_CodeDock");
restoreState(settings.value("windowState").toByteArray);
}
// 实现closeEvent
voidMainWindow::closeEvent(QCloseEvent *event)
{
// 在窗口关闭前,保存布局
QSettingssettings("MyCompany", "MyApp_CodeDock");
settings.setValue("windowState", saveState);
QMainWindow::closeEvent(event);
}
目前,用户可以随心所欲地定制自己的工作区布局,关闭程序再打开,一切都会恢复原样!
总结
通过纯代码的方式,我们更深刻地理解了 QDockWidget 的构建和组织逻辑:
-
核心前提 :它必须与
QMainWindow配合使用,并需要一个centralWidget。 -
创建流程 :
new QDockWidget->dock->setWidget(content)->addDockWidget(Area, dock)。 -
组合技巧 :使用
tabifyDockWidget(dock1, dock2)可以轻松地将多个面板合并为标签页。 -
程序控制 :
toggleViewAction能快速创建控制菜单,setDockNestingEnabled(true)则开启了更自由的布局组合能力。 -
持久化 :结合
saveState,restoreState和QSettings,可以实现专业级的布局保存与恢复。
掌握了纯代码构建 QDockWidget 布局,你就能在程序中根据不同的条件,动态地生成和管理极其复杂的、高度可定制化的用户界面。





















暂无评论内容