【Qt/C++ 桌面开发实战营】第5篇:Qt常用控件全解析
系列介绍
这是系列文章的第五篇,我将带你全面学习Qt提供的各种常用控件。掌握这些控件,你就能搭建出功能完善的桌面应用程序界面。
🎯 本篇你将学到:
-
按钮类控件的使用
-
输入类控件的使用
-
显示类控件的使用
-
列表和表格控件
-
容器类控件
-
实战:构建一个完整的设置对话框
🏆 系列进度:
-
✅ 第1篇:Qt环境搭建与第一个Hello World
-
✅ 第2篇:Qt信号槽机制详解
-
✅ 第3篇:Qt布局管理器完全指南
-
✅ 第4篇:Qt样式表QSS美化教程
-
📝 第5篇:Qt常用控件全解析(本篇)
-
🔜 第6篇:Qt对话框系统
让我们开始吧!
一、控件分类总览
Qt提供了丰富的控件库,按功能可以分为以下几类:
┌─────────────────────────────────────────────────────────────┐ │ Qt控件体系 │ ├─────────────────────────────────────────────────────────────┤ │ 按钮类 │ QPushButton, QToolButton, QRadioButton, │ │ │ QCheckBox, QCommandLinkButton │ ├─────────────────────────────────────────────────────────────┤ │ 输入类 │ QLineEdit, QTextEdit, QPlainTextEdit, │ │ │ QSpinBox, QDoubleSpinBox, QComboBox, │ │ │ QSlider, QDial, QDateTimeEdit │ ├─────────────────────────────────────────────────────────────┤ │ 显示类 │ QLabel, QProgressBar, QLCDNumber, │ │ │ QCalendarWidget, QWebEngineView │ ├─────────────────────────────────────────────────────────────┤ │ 列表/表格类 │ QListWidget, QTableWidget, QTreeWidget, │ │ │ QListView, QTableView, QTreeView │ ├─────────────────────────────────────────────────────────────┤ │ 容器类 │ QGroupBox, QTabWidget, QStackedWidget, │ │ │ QScrollArea, QToolBox, QSplitter │ └─────────────────────────────────────────────────────────────┘
二、按钮类控件
2.1 QPushButton(普通按钮)
最常用的按钮,用于触发操作。
// 基础用法
QPushButton *btn = new QPushButton("确定", this);
btn->setFixedSize(80, 30);
// 设置图标
btn->setIcon(QIcon(":/icons/save.png"));
btn->setIconSize(QSize(20, 20));
// 设置快捷键(Alt+O)
btn->setText("确定(&O)");
// 设置工具提示
btn->setToolTip("点击保存文件");
// 启用/禁用
btn->setEnabled(false);
// 信号
connect(btn, &QPushButton::clicked, this, &MainWindow::onOkClicked);
// 注意:clicked和pressed的区别
// clicked: 按下+释放才触发
// pressed: 按下立即触发
connect(btn, &QPushButton::pressed, this, &MainWindow::onPress);
connect(btn, &QPushButton::released, this, &MainWindow::onRelease);
效果:
┌─────────────────────┐ │ 📁 保存(&O) │ ← 图标 + 文字 + 快捷键提示 └─────────────────────┘ 鼠标悬停时显示:点击保存文件
2.2 QToolButton(工具按钮)
常用于工具栏,可以只显示图标。
QToolButton *toolBtn = new QToolButton(this);
// 只显示图标
toolBtn->setIcon(QIcon(":/icons/edit.png"));
toolBtn->setIconSize(QSize(24, 24));
// 设置样式
toolBtn->setToolButtonStyle(Qt::ToolButtonIconOnly); // 只显示图标
// toolBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); // 图标+文字
// toolBtn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); // 文字在图标下
// 设置弹出菜单
QMenu *menu = new QMenu(toolBtn);
menu->addAction("复制");
menu->addAction("粘贴");
toolBtn->setMenu(menu);
toolBtn->setPopupMode(QToolButton::MenuButtonPopup);
2.3 QRadioButton(单选按钮)
一组单选按钮中,只能选择一个。
// 创建一组单选按钮
QRadioButton *rbMale = new QRadioButton("男", this);
QRadioButton *rbFemale = new QRadioButton("女", this);
QRadioButton *rbOther = new QRadioButton("其他", this);
// 默认选中
rbMale->setChecked(true);
// 获取选中状态
if (rbMale->isChecked()) {
qDebug() << "选择了男";
}
// 信号:选中状态改变时
connect(rbMale, &QRadioButton::toggled, this, [](bool checked) {
qDebug() << "男选中状态:" << checked;
});
重要: 同一父窗口下的单选按钮会自动互斥。如果需要分组,使用QGroupBox:
QGroupBox *group1 = new QGroupBox("性别");
QVBoxLayout *layout1 = new QVBoxLayout(group1);
layout1->addWidget(rbMale);
layout1->addWidget(rbFemale);
QGroupBox *group2 = new QGroupBox("学历");
QVBoxLayout *layout2 = new QVBoxLayout(group2);
layout2->addWidget(new QRadioButton("本科"));
layout2->addWidget(new QRadioButton("硕士"));
layout2->addWidget(new QRadioButton("博士"));
// 这两组单选按钮互不影响
2.4 QCheckBox(复选框)
可以多选,有三种状态(选中、未选中、半选)。
QCheckBox *cbAgree = new QCheckBox("我同意用户协议", this);
QCheckBox *cbRemember = new QCheckBox("记住密码", this);
// 设置三态模式(用于树形结构中的部分选中)
QCheckBox *cbChildren = new QCheckBox("全选", this);
cbChildren->setTristate(true); // 启用三态
// 获取状态
if (cbAgree->isChecked()) {
qDebug() << "已同意";
}
// 信号
connect(cbAgree, &QCheckBox::stateChanged, this, [](int state) {
// Qt::Checked = 2 已选中
// Qt::Unchecked = 0 未选中
// Qt::PartiallyChecked = 1 部分选中
if (state == Qt::Checked) {
qDebug() << "已勾选";
}
});
三、输入类控件
3.1 QLineEdit(单行输入框)
QLineEdit *edit = new QLineEdit(this);
// 设置占位文本
edit->setPlaceholderText("请输入用户名");
// 设置文本
edit->setText("默认文字");
// 获取文本
QString text = edit->text();
// 设置输入限制
edit->setMaxLength(20); // 最大长度
edit->setEchoMode(QLineEdit::Password); // 密码模式
// QLineEdit::Normal 正常显示
// QLineEdit::Password 显示为●
// QLineEdit::NoEcho 不显示任何字符
// 设置输入掩码
edit->setInputMask("999-9999-9999"); // 手机号格式
// 设置验证器
QIntValidator *validator = new QIntValidator(0, 100, this);
edit->setValidator(validator); // 只允许输入0-100的数字
// 清空按钮(Qt 5.2+)
edit->setClearButtonEnabled(true);
// 信号
connect(edit, &QLineEdit::textChanged, this, [](const QString &text) {
qDebug() << "文本改变:" << text;
});
connect(edit, &QLineEdit::returnPressed, this, []() {
qDebug() << "按下回车键";
});
EchoMode效果对比:
┌─────────────────────┐ ┌─────────────────────┐ │ 张三 │ │ ●●●● │ │ Normal │ │ Password │ └─────────────────────┘ └─────────────────────┘ ┌─────────────────────┐ ┌─────────────────────┐ │ (空白) │ │ 123-4567-8901 │ │ NoEcho │ │ InputMask │ └─────────────────────┘ └─────────────────────┘
3.2 QTextEdit(多行富文本输入框)
QTextEdit *textEdit = new QTextEdit(this);
// 设置文本
textEdit->setPlainText("普通文本"); // 纯文本
textEdit->setHtml("<b>粗体</b>文本"); // HTML格式
// 获取文本
QString plainText = textEdit->toPlainText();
QString html = textEdit->toHtml();
// 设置字体
QFont font("微软雅黑", 12);
textEdit->setFont(font);
// 设置只读
textEdit->setReadOnly(true);
// 自动换行
textEdit->setLineWrapMode(QTextEdit::WidgetWidth);
// 添加内容
textEdit->append("追加一行文字");
// 清空
textEdit->clear();
3.3 QPlainTextEdit(多行纯文本输入框)
比QTextEdit更轻量,适合显示大量纯文本。
QPlainTextEdit *plainEdit = new QPlainTextEdit(this); // 设置最大行数(用于日志显示) plainEdit->setMaximumBlockCount(1000); // 最多保存1000行 // 自动滚动到底部 plainEdit->moveCursor(QTextCursor::End);
3.4 QSpinBox 和 QDoubleSpinBox(数字输入框)
// 整数输入
QSpinBox *spinBox = new QSpinBox(this);
spinBox->setRange(1, 100); // 范围1-100
spinBox->setValue(50); // 默认值
spinBox->setSingleStep(5); // 步长
spinBox->setSuffix(" 个"); // 后缀
spinBox->setPrefix("数量: "); // 前缀
// 小数输入
QDoubleSpinBox *doubleSpin = new QDoubleSpinBox(this);
doubleSpin->setRange(0.0, 100.0);
doubleSpin->setDecimals(2); // 小数位数
doubleSpin->setValue(25.5);
doubleSpin->setSingleStep(0.5);
// 信号
connect(spinBox, QOverload<int>::of(&QSpinBox::valueChanged),
this, [](int value) {
qDebug() << "值改变:" << value;
});
效果:
┌─────────────────────────┐ │ 数量: 50 个 ▲ │ │ ▼ │ └─────────────────────────┘
3.5 QComboBox(下拉选择框)
QComboBox *combo = new QComboBox(this);
// 添加选项
combo->addItem("选项1");
combo->addItem("选项2");
combo->addItems({"选项3", "选项4", "选项5"});
// 添加带图标的选项
combo->addItem(QIcon(":/icons/star.png"), "收藏");
// 设置当前选中
combo->setCurrentIndex(0); // 按索引
combo->setCurrentText("选项2"); // 按文本
// 获取选中
int index = combo->currentIndex();
QString text = combo->currentText();
// 可编辑(允许用户输入)
combo->setEditable(true);
// 自动补全
combo->setEditable(true);
QCompleter *completer = new QCompleter(combo->model(), combo);
completer->setFilterMode(Qt::MatchContains);
combo->setCompleter(completer);
// 信号
connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, [](int index) {
qDebug() << "切换到索引:" << index;
});
3.6 QSlider(滑动条)
QSlider *slider = new QSlider(Qt::Horizontal, this); // 水平
// QSlider *slider = new QSlider(Qt::Vertical, this); // 垂直
slider->setRange(0, 100);
slider->setValue(50);
slider->setTickPosition(QSlider::TicksBelow); // 刻度位置
slider->setTickInterval(10); // 刻度间隔
// 信号
connect(slider, &QSlider::valueChanged, this, [](int value) {
qDebug() << "滑动到:" << value;
});
connect(slider, &QSlider::sliderPressed, this, []() {
qDebug() << "开始滑动";
});
connect(slider, &QSlider::sliderReleased, this, []() {
qDebug() << "滑动结束";
});
效果:
水平滑动条:
├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
0 10 20 30 40 50 60 70 80 90 100
●━━━━━━━━━━━━━━━━━━━━━○
当前值:65
3.7 QDateTimeEdit(日期时间选择)
// 日期选择
QDateEdit *dateEdit = new QDateEdit(this);
dateEdit->setDate(QDate::currentDate());
dateEdit->setCalendarPopup(true); // 弹出日历
// 时间选择
QTimeEdit *timeEdit = new QTimeEdit(this);
timeEdit->setTime(QTime::currentTime());
// 日期时间选择
QDateTimeEdit *dtEdit = new QDateTimeEdit(this);
dtEdit->setDateTime(QDateTime::currentDateTime());
dtEdit->setDisplayFormat("yyyy-MM-dd HH:mm:ss"); // 显示格式
dtEdit->setMinimumDateTime(QDateTime::currentDateTime());
dtEdit->setMaximumDateTime(QDateTime::currentDateTime().addDays(30));
四、显示类控件
4.1 QLabel(标签)
QLabel *label = new QLabel(this);
// 显示文本
label->setText("Hello World");
// 显示HTML
label->setText("<b>粗体</b> <font color=red>红色</font>");
// 显示图片
QPixmap pixmap(":/images/logo.png");
label->setPixmap(pixmap);
label->setScaledContents(true); // 缩放图片适应标签
// 显示动画
QMovie *movie = new QMovie(":/images/loading.gif");
label->setMovie(movie);
movie->start();
// 设置对齐
label->setAlignment(Qt::AlignCenter);
// Qt::AlignLeft | Qt::AlignCenter | Qt::AlignRight
// Qt::AlignTop | Qt::AlignBottom
// 自动换行
label->setWordWrap(true);
// 设置工具提示
label->setToolTip("这是一段提示");
// 设置伙伴(快捷键关联)
QLabel *nameLabel = new QLabel("用户名(&N):");
QLineEdit *nameEdit = new QLineEdit;
nameLabel->setBuddy(nameEdit); // Alt+N 聚焦到输入框
4.2 QProgressBar(进度条)
QProgressBar *progressBar = new QProgressBar(this);
// 设置范围
progressBar->setRange(0, 100);
progressBar->setValue(0);
// 设置样式(百分比/无文字)
progressBar->setFormat("%p%"); // 显示百分比(默认)
progressBar->setFormat("%v / %m"); // 显示当前值/最大值
progressBar->setFormat(""); // 不显示文字
// 重置方向
progressBar->setOrientation(Qt::Vertical); // 垂直方向
// 设置倒序
progressBar->setInvertedAppearance(true);
// 更新进度
for (int i = 0; i <= 100; i++) {
progressBar->setValue(i);
QThread::msleep(10);
}
// 不确定进度(不知道具体进度时使用)
progressBar->setRange(0, 0); // 显示忙碌动画
4.3 QCalendarWidget(日历控件)
QCalendarWidget *calendar = new QCalendarWidget(this);
// 设置当前日期
calendar->setSelectedDate(QDate::currentDate());
// 设置日期范围
calendar->setMinimumDate(QDate(2024, 1, 1));
calendar->setMaximumDate(QDate(2025, 12, 31));
// 设置首个星期几
calendar->setFirstDayOfWeek(Qt::Monday); // 星期一为第一天
// 设置网格可见
calendar->setGridVisible(true);
// 设置日期格式
calendar->setDateEditEnabled(true);
// 信号
connect(calendar, &QCalendarWidget::selectionChanged, this, [calendar]() {
QDate date = calendar->selectedDate();
qDebug() << "选中日期:" << date.toString("yyyy-MM-dd");
});
connect(calendar, &QCalendarWidget::clicked, this, [](const QDate &date) {
qDebug() << "点击日期:" << date.toString();
});
五、列表/表格类控件
5.1 QListWidget(列表控件)
QListWidget *listWidget = new QListWidget(this);
// 添加项目
listWidget->addItem("项目1");
listWidget->addItem(new QListWidgetItem("项目2"));
// 添加带图标的项目
QListWidgetItem *item = new QListWidgetItem("项目3");
item->setIcon(QIcon(":/icons/file.png"));
listWidget->addItem(item);
// 批量添加
listWidget->addItems({"项目4", "项目5", "项目6"});
// 设置选择模式
listWidget->setSelectionMode(QAbstractItemView::SingleSelection); // 单选
// listWidget->setSelectionMode(QAbstractItemView::MultiSelection); // 多选
// listWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); // Ctrl多选
// 设置排序
listWidget->setSortingEnabled(true);
// 获取选中项
QListWidgetItem *current = listWidget->currentItem();
QString text = current->text();
// 获取所有选中项
QList<QListWidgetItem*> selected = listWidget->selectedItems();
// 删除项目
delete listWidget->takeItem(row); // 删除指定行
listWidget->clear(); // 清空所有
// 信号
connect(listWidget, &QListWidget::currentItemChanged,
this, [](QListWidgetItem *current, QListWidgetItem *previous) {
qDebug() << "从" << (previous ? previous->text() : "无")
<< "切换到" << current->text();
});
connect(listWidget, &QListWidget::itemDoubleClicked,
this, [](QListWidgetItem *item) {
qDebug() << "双击:" << item->text();
});
5.2 QTableWidget(表格控件)
QTableWidget *table = new QTableWidget(this);
// 设置行列数
table->setRowCount(5);
table->setColumnCount(3);
// 设置表头
QStringList headers = {"姓名", "年龄", "城市"};
table->setHorizontalHeaderLabels(headers);
// 设置内容
table->setItem(0, 0, new QTableWidgetItem("张三"));
table->setItem(0, 1, new QTableWidgetItem("25"));
table->setItem(0, 2, new QTableWidgetItem("北京"));
table->setItem(1, 0, new QTableWidgetItem("李四"));
table->setItem(1, 1, new QTableWidgetItem("30"));
table->setItem(1, 2, new QTableWidgetItem("上海"));
// 设置对齐方式
QTableWidgetItem *item = table->item(0, 1);
item->setTextAlignment(Qt::AlignCenter);
// 设置不可编辑
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
// 设置列宽
table->setColumnWidth(0, 100);
table->resizeColumnToContents(1); // 自适应内容
table->horizontalHeader()->setStretchLastSection(true); // 最后一列拉伸
// 设置行高
table->setRowHeight(0, 40);
// 选择模式
table->setSelectionBehavior(QAbstractItemView::SelectRows); // 选择整行
table->setSelectionMode(QAbstractItemView::SingleSelection); // 单选
// 获取选中行
int row = table->currentRow();
QString name = table->item(row, 0)->text();
// 信号
connect(table, &QTableWidget::cellClicked, this, [](int row, int col) {
qDebug() << "点击单元格:" << row << col;
});
connect(table, &QTableWidget::itemChanged, this, [](QTableWidgetItem *item) {
qDebug() << "内容改变:" << item->text();
});
5.3 QTreeWidget(树形控件)
QTreeWidget *tree = new QTreeWidget(this);
// 设置表头
tree->setHeaderLabel("文件列表");
// 创建顶层项目
QTreeWidgetItem *rootItem = new QTreeWidgetItem(tree);
rootItem->setText(0, "我的电脑");
rootItem->setIcon(0, QIcon(":/icons/computer.png"));
// 添加子项目
QTreeWidgetItem *cItem = new QTreeWidgetItem(rootItem);
cItem->setText(0, "C盘");
QTreeWidgetItem *dItem = new QTreeWidgetItem(rootItem);
dItem->setText(0, "D盘");
// 添加孙子项目
QTreeWidgetItem *docItem = new QTreeWidgetItem(cItem);
docItem->setText(0, "Documents");
QTreeWidgetItem *downloadItem = new QTreeWidgetItem(cItem);
downloadItem->setText(0, "Downloads");
// 展开所有项目
tree->expandAll();
// 设置项目可展开(显示箭头)
cItem->setExpanded(true);
// 信号
connect(tree, &QTreeWidget::itemClicked, this, [](QTreeWidgetItem *item, int col) {
qDebug() << "点击:" << item->text(col);
});
connect(tree, &QTreeWidget::itemDoubleClicked, this, [](QTreeWidgetItem *item, int col) {
qDebug() << "双击打开:" << item->text(col);
});
树形结构效果:
▼ 📁 我的电脑 ├─ 📁 C盘 │ ├─ 📁 Documents │ └─ 📁 Downloads └─ 📁 D盘
六、容器类控件
6.1 QGroupBox(分组框)
QGroupBox *groupBox = new QGroupBox("用户信息", this);
QVBoxLayout *layout = new QVBoxLayout(groupBox);
layout->addWidget(new QLabel("姓名:"));
layout->addWidget(new QLineEdit);
layout->addWidget(new QLabel("年龄:"));
layout->addWidget(new QSpinBox);
// 设置复选框(可选启用/禁用分组内容)
groupBox->setCheckable(true);
groupBox->setChecked(true);
// 取消勾选时,分组内所有控件被禁用
6.2 QTabWidget(标签页)
QTabWidget *tabWidget = new QTabWidget(this);
// 创建页面
QWidget *page1 = new QWidget;
QVBoxLayout *layout1 = new QVBoxLayout(page1);
layout1->addWidget(new QLabel("这是第一个标签页"));
layout1->addWidget(new QPushButton("按钮1"));
tabWidget->addTab(page1, "页面1");
// 第二个页面
QWidget *page2 = new QWidget;
QVBoxLayout *layout2 = new QVBoxLayout(page2);
layout2->addWidget(new QLabel("这是第二个标签页"));
layout2->addWidget(new QPushButton("按钮2"));
tabWidget->addTab(page2, "页面2");
// 添加带图标的标签页
tabWidget->addTab(new QWidget, QIcon(":/icons/settings.png"), "设置");
// 设置标签位置
tabWidget->setTabPosition(QTabWidget::North); // 顶部(默认)
// QTabWidget::South 底部
// QTabWidget::West 左侧
// QTabWidget::East 右侧
// 设置标签形状
tabWidget->setTabShape(QTabWidget::Rounded); // 圆角(默认)
// QTabWidget::Triangular 三角形
// 设置是否可关闭
tabWidget->setTabsClosable(true);
connect(tabWidget, &QTabWidget::tabCloseRequested, this, [tabWidget](int index) {
tabWidget->removeTab(index);
});
// 信号
connect(tabWidget, &QTabWidget::currentChanged, this, [](int index) {
qDebug() << "切换到标签页:" << index;
});
6.3 QStackedWidget(堆叠窗口)
一次只显示一个页面,适合做向导界面。
QStackedWidget *stacked = new QStackedWidget(this);
// 创建多个页面
QWidget *page1 = new QWidget;
page1->setStyleSheet("background-color: red;");
QWidget *page2 = new QWidget;
page2->setStyleSheet("background-color: green;");
QWidget *page3 = new QWidget;
page3->setStyleSheet("background-color: blue;");
stacked->addWidget(page1);
stacked->addWidget(page2);
stacked->addWidget(page3);
// 切换页面
stacked->setCurrentIndex(0); // 按索引
stacked->setCurrentWidget(page2); // 按控件
// 导航按钮
QPushButton *prevBtn = new QPushButton("上一步");
QPushButton *nextBtn = new QPushButton("下一步");
connect(prevBtn, &QPushButton::clicked, [stacked]() {
int index = stacked->currentIndex();
if (index > 0) stacked->setCurrentIndex(index - 1);
});
connect(nextBtn, &QPushButton::clicked, [stacked]() {
int index = stacked->currentIndex();
if (index < stacked->count() - 1) stacked->setCurrentIndex(index + 1);
});
6.4 QScrollArea(滚动区域)
QScrollArea *scrollArea = new QScrollArea(this);
// 创建一个很大的内容控件
QWidget *content = new QWidget;
QVBoxLayout *layout = new QVBoxLayout(content);
for (int i = 0; i < 50; i++) {
layout->addWidget(new QLabel(QString("第%1行").arg(i)));
}
content->setMinimumHeight(2000); // 内容高度超过窗口
// 设置滚动区域
scrollArea->setWidget(content);
scrollArea->setWidgetResizable(true); // 是否自适应
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
6.5 QSplitter(可拖动分割条)
// 水平分割
QSplitter *hSplitter = new QSplitter(Qt::Horizontal, this);
hSplitter->addWidget(new QTextEdit);
hSplitter->addWidget(new QTextEdit);
hSplitter->setSizes({300, 500}); // 设置初始大小
// 垂直分割
QSplitter *vSplitter = new QSplitter(Qt::Vertical, this);
vSplitter->addWidget(new QListWidget);
vSplitter->addWidget(new QTextEdit);
// 嵌套分割
QSplitter *mainSplitter = new QSplitter(Qt::Horizontal, this);
mainSplitter->addWidget(new QListWidget); // 左侧
mainSplitter->addWidget(vSplitter); // 右侧(垂直分割)
效果:
┌───────┬─────────────────────────────┐ │ │ │ │ 列表 │ 内容区域 │ │ │ │ │ ├─────────────────────────────┤ │ │ 底部区域 │ └───────┴─────────────────────────────┘ ↑ ↑ 可拖动分割线 可拖动分割线
七、实战:完整的设置对话框
class SettingsDialog : public QDialog
{
Q_OBJECT
public:
SettingsDialog(QWidget *parent = nullptr) : QDialog(parent)
{
setWindowTitle("设置");
setModal(true);
resize(500, 400);
setupUI();
loadSettings();
}
private:
void setupUI()
{
QVBoxLayout *mainLayout = new QVBoxLayout(this);
// 创建标签页
QTabWidget *tabWidget = new QTabWidget;
// ========== 常规设置 ==========
QWidget *generalWidget = new QWidget;
QFormLayout *generalLayout = new QFormLayout(generalWidget);
// 语言选择
m_langCombo = new QComboBox;
m_langCombo->addItems({"简体中文", "English"});
generalLayout->addRow("语言:", m_langCombo);
// 启动时检查更新
m_checkUpdate = new QCheckBox("启动时检查更新");
generalLayout->addRow("", m_checkUpdate);
// 主题选择
m_themeCombo = new QComboBox;
m_themeCombo->addItems({"深色主题", "浅色主题"});
generalLayout->addRow("主题:", m_themeCombo);
// ========== PDF设置 ==========
QWidget *pdfWidget = new QWidget;
QFormLayout *pdfLayout = new QFormLayout(pdfWidget);
// 默认压缩质量
m_compressQuality = new QSlider(Qt::Horizontal);
m_compressQuality->setRange(1, 100);
m_compressQuality->setValue(70);
m_compressQuality->setTickPosition(QSlider::TicksBelow);
m_compressQuality->setTickInterval(10);
m_qualityLabel = new QLabel("70%");
QHBoxLayout *qualityLayout = new QHBoxLayout;
qualityLayout->addWidget(m_compressQuality);
qualityLayout->addWidget(m_qualityLabel);
pdfLayout->addRow("默认压缩质量:", qualityLayout);
// 输出目录
m_outputDir = new QLineEdit;
m_outputDir->setReadOnly(true);
QPushButton *browseBtn = new QPushButton("浏览");
QHBoxLayout *dirLayout = new QHBoxLayout;
dirLayout->addWidget(m_outputDir);
dirLayout->addWidget(browseBtn);
pdfLayout->addRow("默认输出目录:", dirLayout);
// ========== 高级设置 ==========
QWidget *advancedWidget = new QWidget;
QVBoxLayout *advancedLayout = new QVBoxLayout(advancedWidget);
// 日志级别
m_logLevel = new QComboBox;
m_logLevel->addItems({"调试", "信息", "警告", "错误"});
QFormLayout *formLayout = new QFormLayout;
formLayout->addRow("日志级别:", m_logLevel);
advancedLayout->addLayout(formLayout);
// 功能开关
m_enableAutoSave = new QCheckBox("启用自动保存");
m_enableBackup = new QCheckBox("输出文件时备份原文件");
advancedLayout->addWidget(m_enableAutoSave);
advancedLayout->addWidget(m_enableBackup);
advancedLayout->addStretch();
// 添加标签页
tabWidget->addTab(generalWidget, "常规");
tabWidget->addTab(pdfWidget, "PDF");
tabWidget->addTab(advancedWidget, "高级");
// ========== 按钮 ==========
QDialogButtonBox *buttonBox = new QDialogButtonBox(
QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Apply
);
// 连接信号槽
connect(m_compressQuality, &QSlider::valueChanged, this, [this](int value) {
m_qualityLabel->setText(QString("%1%").arg(value));
});
connect(browseBtn, &QPushButton::clicked, this, [this]() {
QString dir = QFileDialog::getExistingDirectory(this, "选择输出目录");
if (!dir.isEmpty()) {
m_outputDir->setText(dir);
}
});
connect(buttonBox, &QDialogButtonBox::accepted, this, &SettingsDialog::saveAndClose);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
connect(buttonBox->button(QDialogButtonBox::Apply), &QPushButton::clicked,
this, &SettingsDialog::applySettings);
// 组装布局
mainLayout->addWidget(tabWidget);
mainLayout->addWidget(buttonBox);
}
void loadSettings()
{
QSettings settings("MyCompany", "PDFToolbox");
m_langCombo->setCurrentIndex(settings.value("language", 0).toInt());
m_checkUpdate->setChecked(settings.value("checkUpdate", true).toBool());
m_themeCombo->setCurrentIndex(settings.value("theme", 0).toInt());
m_compressQuality->setValue(settings.value("compressQuality", 70).toInt());
m_outputDir->setText(settings.value("outputDir", QDir::homePath()).toString());
m_logLevel->setCurrentIndex(settings.value("logLevel", 1).toInt());
m_enableAutoSave->setChecked(settings.value("autoSave", true).toBool());
m_enableBackup->setChecked(settings.value("backup", true).toBool());
}
void saveSettings()
{
QSettings settings("MyCompany", "PDFToolbox");
settings.setValue("language", m_langCombo->currentIndex());
settings.setValue("checkUpdate", m_checkUpdate->isChecked());
settings.setValue("theme", m_themeCombo->currentIndex());
settings.setValue("compressQuality", m_compressQuality->value());
settings.setValue("outputDir", m_outputDir->text());
settings.setValue("logLevel", m_logLevel->currentIndex());
settings.setValue("autoSave", m_enableAutoSave->isChecked());
settings.setValue("backup", m_enableBackup->isChecked());
}
void applySettings()
{
saveSettings();
// 发出信号通知主窗口应用新设置
emit settingsApplied();
}
void saveAndClose()
{
saveSettings();
accept();
}
signals:
void settingsApplied();
private:
QComboBox *m_langCombo;
QCheckBox *m_checkUpdate;
QComboBox *m_themeCombo;
QSlider *m_compressQuality;
QLabel *m_qualityLabel;
QLineEdit *m_outputDir;
QComboBox *m_logLevel;
QCheckBox *m_enableAutoSave;
QCheckBox *m_enableBackup;
};
八、控件选择指南
| 需求场景 | 推荐控件 | 说明 |
|---|---|---|
| 触发操作 | QPushButton | 最常用 |
| 工具栏按钮 | QToolButton | 可只显示图标 |
| 二选一 | QRadioButton | 互斥 |
| 多选 | QCheckBox | 可独立选择 |
| 单行输入 | QLineEdit | 用户名、密码等 |
| 多行输入 | QTextEdit/QPlainTextEdit | 备注、日志 |
| 数字输入 | QSpinBox/QDoubleSpinBox | 年龄、价格 |
| 下拉选择 | QComboBox | 性别、城市 |
| 范围选择 | QSlider | 音量、亮度 |
| 日期选择 | QDateTimeEdit | 生日、截止日期 |
| 列表展示 | QListWidget | 简单列表 |
| 表格展示 | QTableWidget | 多列数据 |
| 树形展示 | QTreeWidget | 目录结构 |
| 页面切换 | QTabWidget | 标签页 |
| 向导界面 | QStackedWidget | 安装向导 |
九、本课小结
通过本篇学习,你掌握了:
✅ 按钮类控件:QPushButton、QRadioButton、QCheckBox
✅ 输入类控件:QLineEdit、QTextEdit、QSpinBox、QComboBox
✅ 显示类控件:QLabel、QProgressBar、QCalendarWidget
✅ 列表/表格类控件:QListWidget、QTableWidget、QTreeWidget
✅ 容器类控件:QGroupBox、QTabWidget、QSplitter
✅ 实战:完整的设置对话框
下一课预告:
第6篇「Qt对话框系统」——我们将学习Qt中各种对话框的使用,包括消息框、文件对话框、输入对话框,以及如何创建自定义对话框!
系列进度
| 状态 | 篇数 | 文章标题 |
|---|---|---|
| ✅ 已完成 | 第1篇 | Qt环境搭建与第一个Hello World |
| ✅ 已完成 | 第2篇 | Qt信号槽机制详解 |
| ✅ 已完成 | 第3篇 | Qt布局管理器完全指南 |
| ✅ 已完成 | 第4篇 | Qt样式表QSS美化教程 |
| ✅ 已完成 | 第5篇 | Qt常用控件全解析 |
| 🔜 待发布 | 第6篇 | Qt对话框系统 |
如果觉得有用,欢迎点赞、收藏、关注!
下期见!👋
更多推荐

所有评论(0)