跳转到内容
新建笔记

Qt 控件选型:数值输入、选项列表与页面容器

先按用户要完成的动作选控件

跳转到“先按用户要完成的动作选控件”

原笔记汇集了数值输入、选项选择、条目列表和容器控件。它们都属于 Qt Widgets 界面开发,但职责不同:输入控件保存用户选择,容器控件组织其他控件,布局负责分配空间。

需求常用控件关键区别
输入有范围的整数QSpinBox数值与单位显示可以分开处理;小数用 QDoubleSpinBox
从候选项中选一个QComboBox用紧凑下拉框显示候选项,可按需求允许编辑
同时看到多个条目并选择QListWidget条目式便捷列表;复杂或共享数据可考虑 QListView 与模型

转速输入示例设置范围 0~10000,初值 600,后缀为 RPM。后缀只用于显示,程序仍应通过 value() 获取整数,不需要从显示文本里手动删除单位。QSpinBox 文档

转速输入框截图:左侧“转速范围”,右侧显示10000 RPM和上下调整箭头

原图显示的是 10000 RPM,原代码初值是 600;这只是两个不同状态,不能把截图数值当作代码默认值。范围、步长和零值含义应由业务确定,示例数字不代表电机的实际能力。

QComboBox:文字不是稳定标识

跳转到“QComboBox:文字不是稳定标识”

下拉框可以显示 “Option 1” 等文字,但业务上最好同时保存稳定数据,例如整数编号或枚举值,并通过 currentData() 获取。这样重命名和翻译选项不会改变业务含义。

currentIndexChanged 会响应程序设置和用户操作引起的索引变化;activated 主要用于响应用户选择。没有选项时,当前索引可以是 −1,读取数据前应处理空状态。QComboBox 文档

空白下拉框截图:右侧有展开箭头,图中没有可转录的选项文字

QListWidget:选择、排序和拖动

跳转到“QListWidget:选择、排序和拖动”

QListWidgetItem 表示条目,可携带文字、图标、提示等数据。选择模式由 setSelectionMode() 指定:SingleSelection 适合单项,ExtendedSelection 支持常见的组合键多选,MultiSelection 适合逐项切换选择。

排序和手动重排是不同需求。sortItems() 按条目排序;列表内部拖动重排需要显式设置 InternalMove 等拖放行为,不能仅因为类“支持拖放”就假定默认已启用。若要求用户手工控制顺序,通常不应同时开启自动排序。QListWidget、QAbstractItemView 拖放模式

列表截图:第一行“而且”,后面六行“新建项目”,其中一行呈选中状态

这张原图只展示文字和选择效果,不能证明排序或拖放已经配置。数量变化和空状态的处理另见列表数量变化。

保存为 main.cpp。正常运行显示界面;附加 --test 参数检查数值约束、稳定选项数据和列表选择状态。

#include <QApplication>
#include <QComboBox>
#include <QDebug>
#include <QFormLayout>
#include <QListWidget>
#include <QSpinBox>
#include <QVariant>
#include <QWidget>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget window;
window.setWindowTitle(QStringLiteral("输入与选择控件"));
auto *form = new QFormLayout(&window);
auto *speed = new QSpinBox(&window);
speed->setObjectName("minSpeedSpinBox");
speed->setRange(0, 10000);
speed->setValue(600);
speed->setSuffix(QStringLiteral(" RPM"));
form->addRow(QStringLiteral("最小转速"), speed);
auto *mode = new QComboBox(&window);
for (int i = 1; i <= 4; ++i)
mode->addItem(QStringLiteral("Option %1").arg(i), i);
form->addRow(QStringLiteral("模式"), mode);
auto *list = new QListWidget(&window);
list->addItems({QStringLiteral("Item 1"), QStringLiteral("Item 2"),
QStringLiteral("Item 3")});
list->setSelectionMode(QAbstractItemView::SingleSelection);
list->setDragDropMode(QAbstractItemView::InternalMove);
list->setSortingEnabled(false);
form->addRow(QStringLiteral("项目"), list);
if (app.arguments().contains(QStringLiteral("--test"))) {
const auto expect = [](bool ok, const char *message) {
if (!ok)
qFatal("Test failed: %s", message);
};
expect(speed->value() == 600, "initial speed");
speed->setValue(20000);
expect(speed->value() == 10000, "range clamps value");
expect(speed->text().endsWith(" RPM"), "unit suffix");
mode->setCurrentIndex(2);
expect(mode->currentData().toInt() == 3, "stable option data");
list->setCurrentRow(1);
expect(list->count() == 3 && list->selectedItems().size() == 1,
"single selection");
mode->clear();
expect(mode->currentIndex() == -1, "empty combo state");
qInfo() << "Widget selection tests passed";
return 0;
}
window.resize(420, 300);
window.show();
return app.exec();
}

使用下面的 CMakeLists.txt,并配置与 Qt 安装匹配的编译器及 CMAKE_PREFIX_PATH:

cmake_minimum_required(VERSION 3.21)
project(widget_selection_demo LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 REQUIRED COMPONENTS Widgets)
add_executable(widget_selection_demo main.cpp)
target_link_libraries(widget_selection_demo PRIVATE Qt6::Widgets)

本例已在 Windows、Qt 6.10.2、MinGW 下编译,并在 offscreen 模式通过上述状态检查。实际拖动、键盘和触摸操作仍应在目标界面上验证。

原笔记中的容器控件清单

跳转到“原笔记中的容器控件清单”

容器通常负责容纳页面或子控件,不应代替业务模型。原稿列出的名称整理如下;具体行为可从 Qt Widgets 类别索引进入对应文档。

控件主要用途使用时留意
QDockWidget主窗口中的可停靠面板一般配合 QMainWindow 的停靠区域
QFrame带边框或面板外观的基础容器本身不自动安排子控件位置
QGroupBox带标题的逻辑分组,可按需带勾选状态需要为内部控件设置布局
QScrollArea为一个内容控件提供滚动视口多个控件先放进内容容器,再设置布局
QMdiArea管理多个子窗口适合确有多文档窗口需求的界面
QTabWidget用标签切换多个页面每页内部仍需独立布局
QToolBox按分组标题切换内容页适合工具或属性分组
QStackedWidget保存多个页面并显示当前页切换按钮或导航需要另行提供
QWizard管理多步骤向导流程前进、后退与完成逻辑由向导协调
QWizardPage向导中的一个页面与页面校验和字段状态配合

本页重写自控件了解记录。保留全部控件名称、转速范围及初值、四个下拉选项、列表功能意图和三张图片;将图片可读内容转为文字,去掉双层代码围栏和完全重复的列表程序,并补齐完整示例。