一文畅览 Qt 控件类
一文畅览 Qt 控件类
- 总结 Qt 空间基础知识
- 长期更新中
1. QAction
- 是 Qt 框架中用于表示用户界面动作的核心类,它允许你将操作(如菜单项、工具栏按钮、快捷键)抽象为独立对象。
- 核心功能
- 统一管理:一个动作可同时添加到菜单、工具栏、上下文菜单
- 状态同步:所有关联组件自动同步状态(启用/禁用、选中状态)
- 事件处理:通过信号-槽机制响应操作
- 属性丰富:支持文本、图标、快捷键、工具提示等
1. 基本使用:
// 简单创建
QAction *newAction = new QAction("&New", this); // & 定义快捷键(Alt+N)// 带图标创建
QAction *openAction = new QAction(QIcon(":/icons/open.png"), "&Open", this);// 设置属性
saveAction = new QAction("Save", this);
saveAction->setShortcut(QKeySequence::Save); // 快捷键(Ctrl+S)
saveAction->setStatusTip("Save current document");// 状态栏提示
saveAction->setToolTip("Save document"); // 悬浮提示
- 添加到页面组件
// 添加到菜单
QMenu *fileMenu = menuBar()->addMenu("&File");
fileMenu->addAction(newAction);
fileMenu->addAction(openAction);// 添加到工具栏
QToolBar *fileToolBar = addToolBar("File");
fileToolBar->addAction(saveAction);// 添加到按钮
QPushButton *btn = new QPushButton("Save");
btn->addAction(saveAction); // 支持右键菜单/快捷键
2. 关键特性
- 状态控制
// 启用/禁用
saveAction->setEnabled(false); // 可选中动作(切换状态)
QAction *boldAction = new QAction("Bold", this);
boldAction->setCheckable(true); // 设置为可选中
boldAction->setChecked(false); // 初始状态
- 信号处理
// 连接点击信号
connect(newAction, &QAction::triggered, this, &MainWindow::createNewFile);// 可选中动作的状态变化
connect(boldAction, &QAction::toggled, this, &MainWindow::setTextBold);
- 动作分组
// 创建互斥动作组(如对齐方式)
QActionGroup *alignGroup = new QActionGroup(this);
alignGroup->setExclusive(true); // 互斥选择QAction *leftAlign = new QAction("Left", alignGroup);
leftAlign->setCheckable(true);
QAction *centerAlign = new QAction("Center", alignGroup);
centerAlign->setCheckable(true);// 添加分组到菜单
formatMenu->addActions(alignGroup->actions());
3. 高级用法
- 自定义数据
// 存储关联数据
QAction *colorAction = new QAction("Red", this);
colorAction->setData(QColor(Qt::red)); // 使用时获取数据
void MainWindow::changeColor() {QAction *act = qobject_cast<QAction*>(sender());QColor color = act->data().value<QColor>();
}
- 动态更新菜单
// 更新动作属性
void updateActions() {bool hasSelection = textEdit->textCursor().hasSelection();copyAction->setEnabled(hasSelection);cutAction->setEnabled(hasSelection);
}// 连接文本选择变化信号
connect(textEdit, &QTextEdit::selectionChanged, this, &updateActions);
- 分离动作
// 创建无父对象的动作(需手动管理内存)
QAction *globalAction = new QAction("Global Action");
connect(globalAction, &QAction::triggered, [](){qDebug() << "Global action triggered";
});// 添加到系统托盘等
trayIcon->contextMenu()->addAction(globalAction);
2. QSlider
- QSlider 是 Qt 框架中用于提供数值范围选择的滑动条控件,支持水平和垂直两种方向。下面我将全面介绍其成员函数和使用方法。
1.核心功能概述
数值选择:在设定范围内选择整数值
方向支持:水平 (Qt::Horizontal) 或垂直 (Qt::Vertical)
视觉反馈:显示刻度、当前值和范围
交互方式:鼠标拖动、键盘控制、点击槽道
状态控制:启用/禁用、反转方向、自定义样式
2.构造函数与基本设置
-
- 创建滑块
// 创建水平滑块
QSlider *horizontalSlider = new QSlider(Qt::Horizontal, parentWidget);// 创建垂直滑块
QSlider *verticalSlider = new QSlider(Qt::Vertical, parentWidget);
- -2. 范围与初始值设置
// 设置数值范围 (默认0-99)
slider->setRange(0, 100);// 设置最小值
slider->setMinimum(0);// 设置最大值
slider->setMaximum(100);// 设置当前值
slider->setValue(50);// 获取当前值
int value = slider->value();
3. 关键成员函数详解
-
- 步长控制
// 设置单步增量 (键盘方向键改变量)
slider->setSingleStep(5);// 设置页步增量 (点击槽道改变量)
slider->setPageStep(20);// 设置刻度间隔
slider->setTickInterval(10);
-
- 刻度显示
// 设置刻度位置
slider->setTickPosition(QSlider::NoTicks); // 无刻度
slider->setTickPosition(QSlider::TicksAbove); // 上方/左侧刻度
slider->setTickPosition(QSlider::TicksBelow); // 下方/右侧刻度
slider->setTickPosition(QSlider::TicksBothSides); // 两侧刻度
-
- 方向控制
// 设置方向
slider->setOrientation(Qt::Horizontal); // 水平方向
slider->setOrientation(Qt::Vertical); // 垂直方向// 反转显示 (最大值在左/下)
slider->setInvertedAppearance(true);// 反转键盘控制方向
slider->setInvertedControls(true);
-
- 状态控制
// 启用/禁用滑块
slider->setEnabled(false);// 设置滑块是否可拖动
slider->setSliderDown(true); // 手动设置拖动状态// 检查滑块是否被按下
bool isPressed = slider->isSliderDown();// 设置滑块位置 (不改变实际值)
slider->setSliderPosition(75);
-
- 跟踪模式
// 启用跟踪 (值改变时实时触发信号,默认开启)
slider->setTracking(true);// 禁用跟踪 (只在用户释放滑块时触发信号)
slider->setTracking(false);
4.信号系统
- 信号使用示例
// 连接值改变信号
connect(slider, &QSlider::valueChanged, [](int value) {qDebug() << "当前值:" << value;
});// 连接拖动信号
connect(slider, &QSlider::sliderPressed, []() {qDebug() << "开始拖动滑块";
});// 连接释放信号
connect(slider, &QSlider::sliderReleased, []() {qDebug() << "滑块已释放";
});
3. QTabWidget
1. QTabWidget 概述
- QTabWidget 是 Qt 中用于创建选项卡式界面的容器控件,它允许用户通过点击标签在不同的页面之间切换。每个选项卡包含一个页面(通常是一个 QWidget),用户可以轻松地在不同功能模块间导航。
2. 核心 API 详解
- 2.1 构造函数和基本设置
#include <QTabWidget>
#include <QWidget>
#include <QLabel>// 创建 QTabWidget
QTabWidget *tabWidget = new QTabWidget(parent);// 基本设置方法
tabWidget->setTabPosition(QTabWidget::North); // 设置标签位置
tabWidget->setMovable(true); // 允许用户拖动重新排序标签
tabWidget->setTabsClosable(true); // 在标签上显示关闭按钮
tabWidget->setDocumentMode(true); // 文档模式(更简洁的外观)
tabWidget->setTabShape(QTabWidget::Rounded); // 标签形状
- 2.2 添加和移除选项卡
// 添加选项卡的多种方式
int index = tabWidget->addTab(widget, "Tab Name");
int index = tabWidget->addTab(widget, QIcon("icon.png"), "Tab Name");// 在指定位置插入选项卡
int index = tabWidget->insertTab(position, widget, "Tab Name");
int index = tabWidget->insertTab(position, widget, QIcon("icon.png"), "Tab Name");// 移除选项卡
tabWidget->removeTab(index); // 移除但不删除widget
QWidget* widget = tabWidget->widget(index); // 获取对应widget
delete widget; // 手动删除widget
- 2.3 标签相关操作
// 设置标签文本和图标
tabWidget->setTabText(index, "New Text");
tabWidget->setTabIcon(index, QIcon("new_icon.png"));
tabWidget->setTabToolTip(index, "Tooltip text");
tabWidget->setTabWhatsThis(index, "What's this text");// 获取标签信息
QString text = tabWidget->tabText(index);
QIcon icon = tabWidget->tabIcon(index);
QString toolTip = tabWidget->tabToolTip(index);// 启用/禁用标签
tabWidget->setTabEnabled(index, false); // 禁用特定标签
- 2.4 当前选项卡控制
// 设置和获取当前选项卡
tabWidget->setCurrentIndex(index);
tabWidget->setCurrentWidget(widget);int currentIndex = tabWidget->currentIndex();
QWidget* currentWidget = tabWidget->currentWidget();// 获取选项卡数量
int count = tabWidget->count();
3. 完整示例程序
#include <QApplication>
#include <QTabWidget>
#include <QWidget>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QTextEdit>
#include <QListWidget>
#include <QLineEdit>
#include <QMessageBox>
#include <QIcon>class Tab1 : public QWidget {
public:Tab1(QWidget *parent = nullptr) : QWidget(parent) {QVBoxLayout *layout = new QVBoxLayout(this);QLabel *label = new QLabel("这是第一个选项卡");QTextEdit *textEdit = new QTextEdit();textEdit->setPlaceholderText("在这里输入文本...");layout->addWidget(label);layout->addWidget(textEdit);}
};class Tab2 : public QWidget {
public:Tab2(QTabWidget *tabWidget, QWidget *parent = nullptr) : QWidget(parent), tabWidget(tabWidget) {QVBoxLayout *layout = new QVBoxLayout(this);QLabel *label = new QLabel("列表选项卡");listWidget = new QListWidget();// 添加一些示例项listWidget->addItems({"项目1", "项目2", "项目3", "项目4"});QPushButton *addButton = new QPushButton("添加新项目");connect(addButton, &QPushButton::clicked, this, &Tab2::addNewItem);layout->addWidget(label);layout->addWidget(listWidget);layout->addWidget(addButton);}private slots:void addNewItem() {bool ok;QString text = QInputDialog::getText(this, "添加项目", "输入新项目名称:", QLineEdit::Normal, "", &ok);if (ok && !text.isEmpty()) {listWidget->addItem(text);}}private:QTabWidget *tabWidget;QListWidget *listWidget;
};class Tab3 : public QWidget {
public:Tab3(QWidget *parent = nullptr) : QWidget(parent) {QVBoxLayout *layout = new QVBoxLayout(this);QLabel *label = new QLabel("设置选项卡");QLineEdit *nameEdit = new QLineEdit();nameEdit->setPlaceholderText("输入姓名");QLineEdit *emailEdit = new QLineEdit();emailEdit->setPlaceholderText("输入邮箱");QPushButton *saveButton = new QPushButton("保存设置");connect(saveButton, &QPushButton::clicked, this, &Tab3::saveSettings);layout->addWidget(label);layout->addWidget(new QLabel("姓名:"));layout->addWidget(nameEdit);layout->addWidget(new QLabel("邮箱:"));layout->addWidget(emailEdit);layout->addWidget(saveButton);layout->addStretch(); // 添加弹性空间}private slots:void saveSettings() {QMessageBox::information(this, "保存", "设置已保存!");}
};class MainWindow : public QWidget {
public:MainWindow(QWidget *parent = nullptr) : QWidget(parent) {// 创建主布局QVBoxLayout *mainLayout = new QVBoxLayout(this);// 创建 QTabWidgettabWidget = new QTabWidget();// 配置 QTabWidgettabWidget->setTabPosition(QTabWidget::North);tabWidget->setMovable(true);tabWidget->setTabsClosable(true);tabWidget->setDocumentMode(false);// 创建各个选项卡Tab1 *tab1 = new Tab1();Tab2 *tab2 = new Tab2(tabWidget);Tab3 *tab3 = new Tab3();// 添加选项卡(使用图标和文本)tabWidget->addTab(tab1, QIcon(":/icons/text.png"), "文本编辑");tabWidget->addTab(tab2, QIcon(":/icons/list.png"), "列表管理");tabWidget->addTab(tab3, QIcon(":/icons/settings.png"), "设置");// 创建控制按钮QHBoxLayout *buttonLayout = new QHBoxLayout();QPushButton *addTabButton = new QPushButton("添加新选项卡");QPushButton *removeTabButton = new QPushButton("移除当前选项卡");buttonLayout->addWidget(addTabButton);buttonLayout->addWidget(removeTabButton);buttonLayout->addStretch();// 连接信号槽connect(addTabButton, &QPushButton::clicked, this, &MainWindow::addNewTab);connect(removeTabButton, &QPushButton::clicked, this, &MainWindow::removeCurrentTab);connect(tabWidget, &QTabWidget::tabCloseRequested, this, &MainWindow::onTabCloseRequested);connect(tabWidget, &QTabWidget::currentChanged, this, &MainWindow::onCurrentTabChanged);// 组装界面mainLayout->addWidget(tabWidget);mainLayout->addLayout(buttonLayout);setWindowTitle("QTabWidget 示例");resize(600, 400);}private slots:void addNewTab() {static int counter = 1;QWidget *newTab = new QWidget();QVBoxLayout *layout = new QVBoxLayout(newTab);QLabel *label = new QLabel(QString("动态添加的选项卡 %1").arg(counter++));QTextEdit *textEdit = new QTextEdit();textEdit->setPlaceholderText("这个选项卡是动态添加的...");layout->addWidget(label);layout->addWidget(textEdit);int index = tabWidget->addTab(newTab, QString("动态标签 %1").arg(counter));tabWidget->setCurrentIndex(index);}void removeCurrentTab() {int index = tabWidget->currentIndex();if (index >= 0) {QWidget *widget = tabWidget->widget(index);tabWidget->removeTab(index);delete widget;}}void onTabCloseRequested(int index) {if (index >= 0) {QWidget *widget = tabWidget->widget(index);tabWidget->removeTab(index);delete widget;}}void onCurrentTabChanged(int index) {if (index >= 0) {QString tabName = tabWidget->tabText(index);setWindowTitle(QString("QTabWidget 示例 - %1").arg(tabName));}}private:QTabWidget *tabWidget;
};int main(int argc, char *argv[]) {QApplication app(argc, argv);MainWindow window;window.show();return app.exec();
}
4. 高级功能和自定义
- 4.1 自定义标签栏
#include <QTabBar>// 获取标签栏并进行自定义
QTabBar *tabBar = tabWidget->tabBar();
tabBar->setExpanding(false); // 禁止标签平均扩展
tabBar->setDrawBase(false); // 不绘制基線
tabBar->setElideMode(Qt::ElideRight); // 文本过长时显示省略号// 完全自定义标签栏
class CustomTabBar : public QTabBar {
protected:QSize tabSizeHint(int index) const override {QSize size = QTabBar::tabSizeHint(index);size.setWidth(120); // 固定宽度return size;}void paintEvent(QPaintEvent *event) override {// 自定义绘制代码QTabBar::paintEvent(event);}
};// 使用自定义标签栏
CustomTabBar *customBar = new CustomTabBar();
tabWidget->setTabBar(customBar);
- 4.2 样式表定制
// 基本的样式表定制
tabWidget->setStyleSheet("QTabWidget::pane {"" border: 1px solid #C2C7CB;"" top: -1px;"" background-color: #F0F0F0;""}""QTabWidget::tab-bar {"" alignment: center;""}""QTabBar::tab {"" background-color: #E1E1E1;"" border: 1px solid #C4C4C3;"" padding: 8px 20px;"" margin-right: 2px;""}""QTabBar::tab:selected {"" background-color: #FFFFFF;"" border-bottom-color: #FFFFFF;""}""QTabBar::tab:!selected {"" margin-top: 2px;""}"
);
- 4.3 信号和槽
// 连接各种信号
connect(tabWidget, &QTabWidget::currentChanged, [](int index) {qDebug() << "当前选项卡改变为:" << index;
});connect(tabWidget, &QTabWidget::tabBarClicked, [](int index) {qDebug() << "点击了标签:" << index;
});connect(tabWidget, &QTabWidget::tabBarDoubleClicked, [](int index) {qDebug() << "双击了标签:" << index;
});connect(tabWidget, &QTabWidget::tabCloseRequested, [](int index) {qDebug() << "请求关闭标签:" << index;
});
- 4.4 内存管理
// 正确的内存管理
class SafeTabWidget : public QTabWidget {
public:~SafeTabWidget() {// 清理所有子控件for (int i = count() - 1; i >= 0; --i) {QWidget *widget = this->widget(i);removeTab(i);delete widget;}}
};// 或者使用智能指针(C++11+)
#include <memory>
std::unique_ptr<QTabWidget> tabWidget = std::make_unique<QTabWidget>();
4. Layout
1.核心概念:为什么需要布局管理器?
-
在传统GUI编程中,控件的位置和大小(几何属性)通常通过绝对坐标指定(setGeometry)。这种方式有巨大缺陷:
-
无法自适应:窗口大小改变时,内部控件不会随之调整。
-
平台差异:在不同操作系统或不同主题下,控件默认大小可能不同,导致UI错乱。
-
开发繁琐:手动计算每个控件的位置极其麻烦,且难以维护。
-
Qt的布局管理器(Layout Managers)完美解决了这些问题。它们负责:
-
自动定位和调整:根据用户定义的规则,自动安排子控件的位置和大小。
-
自适应响应:当父窗口大小改变时,自动重新计算所有子控件的布局。
-
内容适配:能根据子控件的“大小提示”(sizeHint、minimumSizeHint)进行合理分配。
2.三大基础布局
1. 水平布局(QHBoxLayout)
-
设计理念:将子控件从左到右(默认)依次水平排列。
-
核心API:
addWidget(QWidget *widget, int stretch = 0, Qt::Alignment alignment = 0):添加一个控件。stretch: 拉伸因子。控制控件在多余空间中分配到的比例。0表示不拉伸。alignment: 对齐方式(如 Qt::AlignTop, Qt::AlignVCenter)。注意:只有在控件未填满布局分配的空间时,对齐才有效。addLayout(QLayout *layout, int stretch = 0):添加一个子布局,实现布局嵌套。addStretch(int stretch = 0):添加一个可拉伸的空间(Spacer),用于将控件推到一边。setSpacing(int spacing):设置控件之间的间距。
- 多控件布局示例:假设我们需要创建一个包含三个按钮的水平栏,并且希望“确定”按钮在右侧,“取消”按钮在左侧,中间是弹簧。
QWidget *window = new QWidget;
QHBoxLayout *hLayout = new QHBoxLayout; // 1. 创建水平布局QPushButton *btnOk = new QPushButton("OK");
QPushButton *btnCancel = new QPushButton("Cancel");
QPushButton *btnHelp = new QPushButton("Help");hLayout->addWidget(btnCancel); // 从左开始添加
hLayout->addStretch(1); // 添加一个拉伸因子为1的弹簧,占据所有额外空间
hLayout->addWidget(btnHelp);
hLayout->addWidget(btnOk);window->setLayout(hLayout); // 2. 将布局设置到父窗口上
window->show();
- 效果:
[ Cancel ]____________________[ Help ][ OK ]
- 当窗口拉宽时,Cancel和Help之间的弹簧会变长,将Help和OK始终推向右端。
2. 垂直布局(QVBoxLayout)
-
设计理念:将子控件从上到下依次垂直排列。其API与QHBoxLayout几乎完全相同。
-
多控件布局示例: 创建一个常见的对话框右侧按钮栏。
QVBoxLayout *vLayout = new QVBoxLayout;vLayout->addWidget(new QPushButton("OK"));
vLayout->addWidget(new QPushButton("Cancel"));
vLayout->addWidget(new QPushButton("Help"));
vLayout->addStretch(1); // 添加一个弹簧,将上面的按钮推到顶部
// 设置布局间距和对齐
vLayout->setSpacing(5); // 按钮间距5像素
// 默认情况下,按钮会拉伸填满宽度。如果我们不希望这样,可以设置对齐方式。
// 但通常需要结合大小策略或固定大小使用,或者放在另一个布局中。
- 效果:
text
[ OK ]
[ Cancel]
[ Help ]
(剩余空间)
3. 栅格布局(QGridLayout)
-
设计理念:将空间划分为行和列的网格,可以将控件放入特定的单元格中。这是最灵活、最常用的复杂布局工具。
-
核心API:
addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment = 0):将控件放入指定的row和column。addWidget(QWidget *widget, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment = 0):高级用法。让控件跨越多行多列。rowSpan: 跨越的行数。columnSpan: 跨越的列数。setRowStretch(int row, int stretch):设置某一行的拉伸因子。setColumnStretch(int column, int stretch):设置某一列的拉伸因子。setRowMinimumHeight(int row, int minSize):设置某一行的最小高度。setColumnMinimumWidth(int column, int minSize):设置某一列的最小宽度。
- 多控件布局示例:创建一个典型的用户登录表单。
QGridLayout *gridLayout = new QGridLayout;QLabel *labelUser = new QLabel("Username:");
QLabel *labelPass = new QLabel("Password:");
QLineEdit *lineEditUser = new QLineEdit;
QLineEdit *lineEditPass = new QLineEdit;
lineEditPass->setEchoMode(QLineEdit::Password);
QPushButton *btnLogin = new QPushButton("Login");
QPushButton *btnCancel = new QPushButton("Cancel");// 添加控件到网格 (行, 列)
gridLayout->addWidget(labelUser, 0, 0); // 第0行,第0列
gridLayout->addWidget(lineEditUser, 0, 1); // 第0行,第1列
gridLayout->addWidget(labelPass, 1, 0); // 第1行,第0列
gridLayout->addWidget(lineEditPass, 1, 1); //第1行,第1列// 按钮放在第2行,跨1行2列,并水平居中
gridLayout->addWidget(btnLogin, 2, 0, 1, 2, Qt::AlignHCenter); // (起始行,起始列,占1行,占2列)// 设置列的拉伸因子,让第1列(输入框)比第0列(标签)更宽
gridLayout->setColumnStretch(1, 3); // 第1列的拉伸因子为3// 也可以设置布局边距和间距
gridLayout->setContentsMargins(10, 10, 10, 10); // 设置布局的外边距(左,上,右,下)
gridLayout->setHorizontalSpacing(5); // 设置水平间距
gridLayout->setVerticalSpacing(10); // 设置垂直间距window->setLayout(gridLayout);
- 效果:
text
Username: [__________________________]
Password: [__________________________][ Login ]
- 当窗口变宽时,只有输入框所在的列会变宽,标签列宽度基本不变。
3. 高级技巧与实战
1. 布局嵌套(组合布局)
-
没有任何一个布局可以单独解决所有问题。复杂的UI都是通过嵌套布局实现的。
-
示例:创建一个经典的文本编辑器界面,有菜单、工具栏、状态栏和中央文本编辑区。
QWidget *mainWindow = new QWidget;
QVBoxLayout *mainLayout = new QVBoxLayout(mainWindow); // 主布局是垂直的// 1. 添加菜单栏(假设是QMenuBar)
mainLayout->addWidget(menuBar);// 2. 添加工具栏(假设是QToolBar)
mainLayout->addWidget(toolBar);// 3. 中央部件
QTextEdit *textEdit = new QTextEdit;
mainLayout->addWidget(textEdit); // 中央文本编辑区占据大部分空间// 4. 底部状态栏
QHBoxLayout *statusLayout = new QHBoxLayout; // 状态栏本身可能又是一个水平布局
statusLayout->addWidget(new QLabel("Ready"));
statusLayout->addStretch();
statusLayout->addWidget(new QLabel("Ln 1, Col 1"));
mainLayout->addLayout(statusLayout); // 将水平布局作为子布局加入主垂直布局// 设置主布局的拉伸因子,确保中央文本编辑区会拉伸
mainLayout->setStretchFactor(textEdit, 1);
2. 拉伸因子(Stretch Factor)的深入理解
-
拉伸因子决定了在父布局空间增长时,子控件或子布局如何分配额外的空间。
-
默认值为0,意味着该控件不希望增长。
-
如果所有控件的拉伸因子都是0,空间会根据大小策略平均分配。
-
因子是比例值。如果一行有两个控件,拉伸因子分别为1和2,那么第一个控件获得1/3的额外空间,第二个获得2/3。
-
当你在网格布局中有两个垂直布局,并且希望在窗口缩放时保持它们的比例不变,可以通过以下几种方法来实现:
方法一:设置拉伸因子(推荐)
这是最常用且最简单的方法,通过设置行列的拉伸因子来控制布局的比例。
#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QLabel>
#include <QTextEdit>class MainWindow : public QWidget {
public:MainWindow(QWidget *parent = nullptr) : QWidget(parent) {// 创建网格布局QGridLayout *gridLayout = new QGridLayout(this);// 创建第一个垂直布局QVBoxLayout *leftLayout = new QVBoxLayout();leftLayout->addWidget(new QLabel("左侧区域"));QTextEdit *leftTextEdit = new QTextEdit();leftTextEdit->setPlaceholderText("这是左侧文本框");leftLayout->addWidget(leftTextEdit);// 创建第二个垂直布局QVBoxLayout *rightLayout = new QVBoxLayout();rightLayout->addWidget(new QLabel("右侧区域"));QTextEdit *rightTextEdit = new QTextEdit();rightTextEdit->setPlaceholderText("这是右侧文本框");rightLayout->addWidget(rightTextEdit);// 将垂直布局添加到网格布局中gridLayout->addLayout(leftLayout, 0, 0); // 第0行,第0列gridLayout->addLayout(rightLayout, 0, 1); // 第0行,第1列// 关键:设置列的拉伸因子来控制比例// 这里设置为1:2的比例,左侧占1/3,右侧占2/3gridLayout->setColumnStretch(0, 1); // 第0列拉伸因子为1gridLayout->setColumnStretch(1, 2); //第1列拉伸因子为2// 可选:设置行拉伸因子(如果有多行的话)// gridLayout->setRowStretch(0, 1);setWindowTitle("布局比例保持示例");resize(800, 600);}
};int main(int argc, char *argv[]) {QApplication app(argc, argv);MainWindow window;window.show();return app.exec();
}
3. 大小策略(QSizePolicy)
-
这是Qt布局系统中另一个核心概念。它定义了控件在布局中如何水平或垂直调整大小。
-
每个QWidget都有一个QSizePolicy。
-
主要属性:
HorizontalPolicy / VerticalPolicy:常见值有:Fixed: 大小不能改变,只使用sizeHint。Minimum: sizeHint是最小大小,可以拉伸,但变大没用。Maximum: sizeHint是最大大小,可以缩小,但不能变大。Preferred: sizeHint是最佳大小,可以缩小到minimumSizeHint,也可以拉伸。Expanding: 和Preferred类似,但非常乐意拉伸,会尽可能多地占用空间(如QTextEdit)。Ignored: 忽略sizeHint,尽可能大(相当于0,1拉伸因子)。
设置方法:widget->setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical);
4. 其他布局和辅助类
QFormLayout:专门为表单设计(标签-字段对),非常方便。它会自动在不同平台上采用该平台的标准表单样式(如macOS的标签右对齐)。Spacer Item(弹簧):除了用addStretch(),还可以显式创建QSpacerItem并addItem(),提供更精确的控制。QStackedLayout:同一时间只显示一个控件,类似于选项卡,但没有标签页头。常用于向导或配置界面。