容器控件
容器控件用于组织和分组其他控件,使界面结构更清晰、更易于管理。
QGroupBox(分组框)
带有标题的边框容器,用于将相关控件分组。
#include <QGroupBox>
#include <QVBoxLayout>
#include <QRadioButton>
// 创建分组框
QGroupBox *groupBox = new QGroupBox("用户设置", this);
// 在分组框中添加控件
QVBoxLayout *layout = new QVBoxLayout();
layout->addWidget(new QRadioButton("选项 A"));
layout->addWidget(new QRadioButton("选项 B"));
layout->addWidget(new QRadioButton("选项 C"));
groupBox->setLayout(layout);
// 设置对齐方式
groupBox->setAlignment(Qt::AlignLeft); // 标题左对齐
// 启用/禁用整个分组
groupBox->setEnabled(false);
// 复选框分组框(可勾选)
QGroupBox *checkableGroup = new QGroupBox("高级选项", this);
checkableGroup->setCheckable(true);
checkableGroup->setChecked(false); // 默认未选中
connect(checkableGroup, &QGroupBox::toggled, this, [=](bool checked) {
qDebug() << "分组框状态:" << checked;
});
QTabWidget(标签页)
通过标签页组织多个页面,节省界面空间。
#include <QTabWidget>
#include <QWidget>
// 创建标签页控件
QTabWidget *tabWidget = new QTabWidget(this);
// 创建页面
QWidget *page1 = new QWidget();
QVBoxLayout *layout1 = new QVBoxLayout(page1);
layout1->addWidget(new QLabel("这是第一页的内容"));
layout1->addWidget(new QPushButton("按钮1"));
QWidget *page2 = new QWidget();
QVBoxLayout *layout2 = new QVBoxLayout(page2);
layout2->addWidget(new QLabel("这是第二页的内容"));
layout2->addWidget(new QLineEdit());
QWidget *page3 = new QWidget();
// ... 设置第三页
// 添加标签页
tabWidget->addTab(page1, "基本信息");
tabWidget->addTab(page2, QIcon(":/icons/settings.png"), "设置");
tabWidget->addTab(page3, "关于");
// 设置当前页
tabWidget->setCurrentIndex(0);
// 标签位置
tabWidget->setTabPosition(QTabWidget::North); // 顶部(默认)
// 其他:South, West, East
// 标签形状
tabWidget->setTabShape(QTabWidget::Rounded); // 圆角(默认)
// QTabWidget::Triangular - 三角形
// 标签可关闭
tabWidget->setTabsClosable(true);
connect(tabWidget, &QTabWidget::tabCloseRequested, this, [=](int index) {
tabWidget->removeTab(index);
});
// 标签可移动
tabWidget->setMovable(true);
// 信号
connect(tabWidget, &QTabWidget::currentChanged, this, [=](int index) {
qDebug() << "切换到标签页:" << index;
});
// 插入标签页到指定位置
tabWidget->insertTab(1, newPage, "新页面");
// 禁用某个标签
tabWidget->setTabEnabled(2, false);
QStackedWidget(堆叠窗口)
管理多个页面,但只显示一个,常用于向导或切换视图。
#include <QStackedWidget>
// 创建堆叠窗口
QStackedWidget *stackedWidget = new QStackedWidget(this);
// 添加页面
QWidget *page1 = new QWidget();
QWidget *page2 = new QWidget();
QWidget *page3 = new QWidget();
stackedWidget->addWidget(page1); // 返回索引 0
stackedWidget->addWidget(page2); // 返回索引 1
stackedWidget->addWidget(page3); // 返回索引 2
// 切换页面
stackedWidget->setCurrentIndex(1); // 通过索引
stackedWidget->setCurrentWidget(page2); // 通过指针
// 获取当前页
int currentIndex = stackedWidget->currentIndex();
QWidget *currentPage = stackedWidget->currentWidget();
// 与按钮配合实现页面切换
QPushButton *nextBtn = new QPushButton("下一步", this);
connect(nextBtn, &QPushButton::clicked, this, [=]() {
int next = stackedWidget->currentIndex() + 1;
if (next < stackedWidget->count()) {
stackedWidget->setCurrentIndex(next);
}
});
QPushButton *prevBtn = new QPushButton("上一步", this);
connect(prevBtn, &QPushButton::clicked, this, [=]() {
int prev = stackedWidget->currentIndex() - 1;
if (prev >= 0) {
stackedWidget->setCurrentIndex(prev);
}
});
QScrollArea(滚动区域)
当内容超出显示区域时提供滚动条。
#include <QScrollArea>
#include <QWidget>
#include <QVBoxLayout>
// 创建滚动区域
QScrollArea *scrollArea = new QScrollArea(this);
// 创建内容窗口
QWidget *contentWidget = new QWidget();
QVBoxLayout *layout = new QVBoxLayout(contentWidget);
// 添加大量内容
for (int i = 0; i < 50; i++) {
layout->addWidget(new QPushButton(QString("按钮 %1").arg(i)));
}
// 设置内容
scrollArea->setWidget(contentWidget);
// 关键设置:让内容窗口自适应
scrollArea->setWidgetResizable(true);
// 滚动条策略
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); // 按需显示
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); // 总是显示
// 其他选项:ScrollBarAlwaysOff(总是隐藏)
// 程序化滚动
scrollArea->verticalScrollBar()->setValue(100); // 滚动到指定位置
// 获取当前滚动位置
int hValue = scrollArea->horizontalScrollBar()->value();
int vValue = scrollArea->verticalScrollBar()->value();
QSplitter(分割器)
允许用户拖动调整子控件的大小。
#include <QSplitter>
#include <QTextEdit>
#include <QListWidget>
// 创建水平分割器
QSplitter *splitter = new QSplitter(Qt::Horizontal, this);
// 添加子控件
QListWidget *listWidget = new QListWidget();
listWidget->addItems({"项目1", "项目2", "项目3"});
QTextEdit *textEdit = new QTextEdit();
textEdit->setPlainText("右侧编辑区域");
QTreeWidget *treeWidget = new QTreeWidget();
splitter->addWidget(listWidget);
splitter->addWidget(textEdit);
splitter->addWidget(treeWidget);
// 设置初始比例
splitter->setSizes(QList<int>() << 200 << 400 << 200);
// 设置拉伸因子
splitter->setStretchFactor(0, 1); // 第一个控件拉伸因子1
splitter->setStretchFactor(1, 3); // 第二个控件拉伸因子3(占更多空间)
// 设置最小尺寸
splitter->setMinimumSize(600, 400);
// 保存/恢复分割状态
QSettings settings;
settings.setValue("splitterState", splitter->saveState());
splitter->restoreState(settings.value("splitterState").toByteArray());
// 嵌套分割器
QSplitter *vSplitter = new QSplitter(Qt::Vertical);
vSplitter->addWidget(topWidget);
vSplitter->addWidget(splitter); // 水平分割器作为子控件
QFrame(框架)
带边框的基础容器,可用于视觉分隔。
#include <QFrame>
// 创建框架
QFrame *frame = new QFrame(this);
// 设置边框样式
frame->setFrameShape(QFrame::StyledPanel); // 样式面板
frame->setFrameShadow(QFrame::Raised); // 凸起效果
// 形状选项:NoFrame, Box, Panel, StyledPanel, HLine, VLine
// 阴影选项:Plain, Raised, Sunken
// 设置线宽
frame->setLineWidth(2);
frame->setMidLineWidth(1);
// 常用作水平/垂直分隔线
QFrame *hLine = new QFrame(this);
hLine->setFrameShape(QFrame::HLine);
hLine->setFrameShadow(QFrame::Sunken);
QFrame *vLine = new QFrame(this);
vLine->setFrameShape(QFrame::VLine);
vLine->setFrameShadow(QFrame::Sunken);
// 配合布局使用
QVBoxLayout *layout = new QVBoxLayout();
layout->addWidget(section1);
layout->addWidget(hLine); // 分隔线
layout->addWidget(section2);
QDockWidget(停靠窗口)
可停靠、浮动、关闭的面板,常用于 IDE 风格的界面。
#include <QDockWidget>
#include <QMainWindow>
#include <QTextEdit>
// 需要在 QMainWindow 中使用
QMainWindow *mainWindow = new QMainWindow();
// 创建停靠窗口
QDockWidget *dock1 = new QDockWidget("文件浏览器", mainWindow);
QTreeWidget *tree = new QTreeWidget();
dock1->setWidget(tree);
QDockWidget *dock2 = new QDockWidget("属性", mainWindow);
QTableWidget *table = new QTableWidget();
dock2->setWidget(table);
// 添加到主窗口
mainWindow->addDockWidget(Qt::LeftDockWidgetArea, dock1);
mainWindow->addDockWidget(Qt::RightDockWidgetArea, dock2);
// 停靠区域选项
// Qt::LeftDockWidgetArea, Qt::RightDockWidgetArea
// Qt::TopDockWidgetArea, Qt::BottomDockWidgetArea
// Qt::AllDockWidgetAreas
// 设置特性
dock1->setFeatures(QDockWidget::DockWidgetMovable |
QDockWidget::DockWidgetFloatable);
// 特性选项:
// DockWidgetClosable - 可关闭
// DockWidgetMovable - 可移动
// DockWidgetFloatable - 可浮动
// DockWidgetVerticalTitleBar - 垂直标题栏
// AllDockWidgetFeatures - 所有特性
// NoDockWidgetFeatures - 无特性
// 信号
connect(dock1, &QDockWidget::visibilityChanged, this, [=](bool visible) {
qDebug() << "停靠窗口可见性:" << visible;
});
connect(dock1, &QDockWidget::topLevelChanged, this, [=](bool floating) {
qDebug() << "是否浮动:" << floating;
});
// 分割停靠区域
mainWindow->splitDockWidget(dock1, dock2, Qt::Horizontal);
// 标签化停靠(Qt 5.6+)
mainWindow->tabifyDockWidget(dock1, dock2);
QMdiArea(多文档区域)
实现多文档界面(MDI),同时管理多个子窗口。
#include <QMdiArea>
#include <QMdiSubWindow>
#include <QTextEdit>
// 创建 MDI 区域
QMdiArea *mdiArea = new QMdiArea(this);
// 创建子窗口
QMdiSubWindow *subWindow1 = new QMdiSubWindow();
subWindow1->setWidget(new QTextEdit());
subWindow1->setWindowTitle("文档 1");
mdiArea->addSubWindow(subWindow1);
QMdiSubWindow *subWindow2 = new QMdiSubWindow();
subWindow2->setWidget(new QTextEdit());
subWindow2->setWindowTitle("文档 2");
mdiArea->addSubWindow(subWindow2);
// 显示子窗口
subWindow1->show();
subWindow2->show();
// 视图模式
mdiArea->setViewMode(QMdiArea::SubWindowView); // 子窗口视图(默认)
// mdiArea->setViewMode(QMdiArea::TabbedView); // 标签页视图
// 排列子窗口
mdiArea->tileSubWindows(); // 平铺
mdiArea->cascadeSubWindows(); // 层叠
// 激活窗口
mdiArea->setActiveSubWindow(subWindow1);
// 信号
connect(mdiArea, &QMdiArea::subWindowActivated, this, [=](QMdiSubWindow *window) {
if (window) {
qDebug() << "激活窗口:" << window->windowTitle();
}
});
// 关闭所有子窗口
mdiArea->closeAllSubWindows();
完整示例:复杂界面布局
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr) : QMainWindow(parent)
{
setWindowTitle("复杂布局示例");
resize(1000, 700);
// 创建中央部件 - 分割器
QSplitter *mainSplitter = new QSplitter(Qt::Horizontal, this);
setCentralWidget(mainSplitter);
// 左侧 - 文件浏览器
QDockWidget *fileDock = new QDockWidget("文件", this);
QTreeWidget *fileTree = new QTreeWidget();
fileTree->setHeaderLabel("文件列表");
fileDock->setWidget(fileTree);
addDockWidget(Qt::LeftDockWidgetArea, fileDock);
// 中间 - 标签页
QTabWidget *tabWidget = new QTabWidget();
// 第一页 - 表单
QWidget *formPage = new QWidget();
QFormLayout *formLayout = new QFormLayout(formPage);
formLayout->addRow("姓名:", new QLineEdit());
formLayout->addRow("年龄:", new QSpinBox());
formLayout->addRow("备注:", new QTextEdit());
tabWidget->addTab(formPage, "基本信息");
// 第二页 - 设置
QWidget *settingsPage = new QWidget();
QVBoxLayout *settingsLayout = new QVBoxLayout(settingsPage);
QGroupBox *group1 = new QGroupBox("显示设置");
QVBoxLayout *group1Layout = new QVBoxLayout(group1);
group1Layout->addWidget(new QCheckBox("显示工具栏"));
group1Layout->addWidget(new QCheckBox("显示状态栏"));
settingsLayout->addWidget(group1);
settingsLayout->addStretch();
tabWidget->addTab(settingsPage, "设置");
// 第三页 - 带滚动区域
QScrollArea *scrollArea = new QScrollArea();
QWidget *scrollContent = new QWidget();
QVBoxLayout *scrollLayout = new QVBoxLayout(scrollContent);
for (int i = 0; i < 20; i++) {
scrollLayout->addWidget(new QPushButton(QString("按钮 %1").arg(i)));
}
scrollArea->setWidget(scrollContent);
scrollArea->setWidgetResizable(true);
tabWidget->addTab(scrollArea, "长列表");
mainSplitter->addWidget(tabWidget);
// 右侧 - 属性面板
QDockWidget *propDock = new QDockWidget("属性", this);
QTableWidget *propTable = new QTableWidget(5, 2);
propTable->setHorizontalHeaderLabels({"属性", "值"});
propDock->setWidget(propTable);
addDockWidget(Qt::RightDockWidgetArea, propDock);
// 底部 - 输出面板
QDockWidget *outputDock = new QDockWidget("输出", this);
QTextEdit *outputEdit = new QTextEdit();
outputEdit->setReadOnly(true);
outputDock->setWidget(outputEdit);
addDockWidget(Qt::BottomDockWidgetArea, outputDock);
// 设置分割比例
mainSplitter->setSizes(QList<int>() << 200 << 600 << 200);
// 创建菜单
QMenu *viewMenu = menuBar()->addMenu("视图");
viewMenu->addAction(fileDock->toggleViewAction());
viewMenu->addAction(propDock->toggleViewAction());
viewMenu->addAction(outputDock->toggleViewAction());
}
};
布局选择指南
| 容器 | 适用场景 | 特点 |
|---|---|---|
| QGroupBox | 相关控件分组 | 带标题边框,视觉分组 |
| QTabWidget | 多页面内容 | 标签切换,节省空间 |
| QStackedWidget | 向导、步骤流程 | 程序化切换页面 |
| QScrollArea | 内容超出视口 | 自动滚动条 |
| QSplitter | 可调比例区域 | 用户可拖动调整 |
| QDockWidget | IDE 风格面板 | 可停靠、浮动 |
| QMdiArea | 多文档编辑 | 同时管理多个子窗口 |
下一步
继续学习 高级控件,掌握表格、树形控件等复杂控件的使用。