Qt_常用控件使用学习

文章目录

  • Qt_常用控件
    • 按钮控件
      • [Push Button:命令按钮](#Push Button:命令按钮)
      • [Tool Button:工具按钮](#Tool Button:工具按钮)
      • [Radio Button:单选按钮](#Radio Button:单选按钮)
      • [Check Box:复选框按钮](#Check Box:复选框按钮)
      • [Command Link Button:命令链接按钮](#Command Link Button:命令链接按钮)
      • QDialogButtonBox按钮盒
    • 容器组控件
      • [Group Box:](#Group Box:)
      • ScrollArea:滚动区域
      • [Tool Box:工具箱](#Tool Box:工具箱)
      • [Tab Widget:标签小部件](#Tab Widget:标签小部件)
      • [Frama 框架](#Frama 框架)
      • [Dock Widget:停靠窗体部件](#Dock Widget:停靠窗体部件)
    • [item View 列表控件](#item View 列表控件)
      • QListView
      • [table View](#table View)
      • [list Widget 清单控件](#list Widget 清单控件)
      • [tree Widget 树形控件](#tree Widget 树形控件)
      • [table Widget 表控件](#table Widget 表控件)
    • [input Widgets 输入组控件](#input Widgets 输入组控件)
      • QComboBox
      • QFontComboBox
      • [Line Edit 单行输入框](#Line Edit 单行输入框)
      • [text Edit 多行文本编辑](#text Edit 多行文本编辑)
      • [Spin Box](#Spin Box)
      • [TimeEdit 时间编辑器](#TimeEdit 时间编辑器)
      • [Scroll Bar控件](#Scroll Bar控件)
      • [Key Sequence Edit 快捷键捕获](#Key Sequence Edit 快捷键捕获)
    • [Display Widgets](#Display Widgets)
      • [label :标签](#label :标签)
      • [Text Brower : 文本浏览器](#Text Brower : 文本浏览器)
      • [textBrowser 进度条](#textBrowser 进度条)
      • [LCD Number 液晶数字](#LCD Number 液晶数字)

Qt_常用控件

按钮控件

Push Button:命令按钮

最常用的按钮控件,支持文本、图标、快捷键。

特性 说明
文本显示 支持 & 设置快捷键(如 &OK → Alt+O)
图标支持 setIcon() 设置图标
默认按钮 setDefault(true) 设为回车默认按钮
自动默认 setAutoDefault(true) 焦点所在时自动成为默认按钮
扁平化 setFlat(true) 去除边框,悬停才显示
可选中 setCheckable(true) 切换选中/未选中状态
菜单 setMenu() 绑定下拉菜单
cpp 复制代码
QPushButton *btn = new QPushButton("&OK", parent);
btn->setIcon(QIcon(":/icons/ok.png"));
btn->setDefault(true);
connect(btn, &QPushButton::clicked, [](){ /* 处理点击 */ });

使用示例:

cpp 复制代码
#include <QApplication>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QMessageBox>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QWidget window;
    window.setWindowTitle("QPushButton 示例");
    window.resize(300, 200);

    QVBoxLayout *layout = new QVBoxLayout(&window);

    // 普通按钮
    QPushButton *btn1 = new QPushButton("普通按钮");
    layout->addWidget(btn1);

    // 带快捷键的按钮(Alt+O)
    QPushButton *btn2 = new QPushButton("&OK 按钮");
    layout->addWidget(btn2);

    // 可切换状态的按钮
    QPushButton *btn3 = new QPushButton("切换按钮");
    btn3->setCheckable(true);
    layout->addWidget(btn3);

    // 扁平化按钮
    QPushButton *btn4 = new QPushButton("扁平按钮");
    btn4->setFlat(true);
    layout->addWidget(btn4);

    // 默认按钮(按回车触发)
    QPushButton *btn5 = new QPushButton("默认按钮(Enter)");
    btn5->setDefault(true);
    layout->addWidget(btn5);

    QObject::connect(btn1, &QPushButton::clicked, [&]() {
        QMessageBox::information(&window, "提示", "你点击了普通按钮!");
    });

    QObject::connect(btn3, &QPushButton::toggled, [&](bool checked) {
        btn3->setText(checked ? "已按下" : "切换按钮");
    });

    window.show();
    return app.exec();
}

使用效果:

Tool Button:工具按钮

为工具栏设计,支持多种显示模式和弹出菜单。

特性 说明
显示模式 setToolButtonStyle() 控制图标/文字显示方式
弹出菜单 setPopupMode() 控制菜单弹出行为
自动提升 setAutoRaise(true) 鼠标悬停时才显示凸起效果
可切换 setCheckable(true) 作为开关按钮使用

ToolButtonStyle 枚举值:

说明
Qt::ToolButtonIconOnly 只显示图标(默认)
Qt::ToolButtonTextOnly 只显示文字
Qt::ToolButtonTextBesideIcon 文字在图标旁边
Qt::ToolButtonTextUnderIcon 文字在图标下方
Qt::ToolButtonFollowStyle 跟随系统风格
cpp 复制代码
QToolButton *toolBtn = new QToolButton;
toolBtn->setText("Save");
toolBtn->setIcon(QIcon(":/icons/save.png"));
toolBtn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
toolBtn->setPopupMode(QToolButton::MenuButtonPopup);
toolBtn->setMenu(new QMenu);

使用示例:

cpp 复制代码
#include <QApplication>
#include <QToolButton>
#include <QHBoxLayout>
#include <QMenu>
#include <QWidget>
#include <QMessageBox>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QWidget window;
    window.setWindowTitle("QToolButton 示例");
    window.resize(400, 150);

    QHBoxLayout *layout = new QHBoxLayout(&window);

    // 仅图标按钮
    QToolButton *btn1 = new QToolButton;
    btn1->setText("新建");
    btn1->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
    layout->addWidget(btn1);

    // 带下拉菜单的按钮
    QToolButton *btn2 = new QToolButton;
    btn2->setText("打开");
    btn2->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
    btn2->setPopupMode(QToolButton::MenuButtonPopup);
    QMenu *menu = new QMenu(btn2);
    menu->addAction("最近文件1");
    menu->addAction("最近文件2");
    btn2->setMenu(menu);
    layout->addWidget(btn2);

    // 即时弹出菜单
    QToolButton *btn3 = new QToolButton;
    btn3->setText("更多");
    btn3->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
    btn3->setPopupMode(QToolButton::InstantPopup);
    QMenu *menu2 = new QMenu(btn3);
    menu2->addAction("选项A");
    menu2->addAction("选项B");
    btn3->setMenu(menu2);
    layout->addWidget(btn3);

    // 自动提升(悬停才显示边框)
    QToolButton *btn4 = new QToolButton;
    btn4->setText("悬停我");
    btn4->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
    btn4->setAutoRaise(true);
    layout->addWidget(btn4);

    QObject::connect(btn1, &QToolButton::clicked, [&]() {
        QMessageBox::information(&window, "提示", "点击了新建按钮!");
    });

    window.show();
    return app.exec();
}

使用效果:

Radio Button:单选按钮

同组内只能选中一个,常用于互斥选项。

特性 说明
分组机制 同一父容器内的 Radio Button 自动互斥
手动分组 使用 QButtonGroup 实现跨容器分组
默认选中 setChecked(true) 设置初始选中项
信号 toggled(bool) 选中状态变化时触发
cpp 复制代码
QRadioButton *radio1 = new QRadioButton("Option A");
QRadioButton *radio2 = new QRadioButton("Option B");
radio1->setChecked(true);

// 使用 QButtonGroup 获取选中 ID
QButtonGroup *group = new QButtonGroup;
group->addButton(radio1, 0);
group->addButton(radio2, 1);
connect(group, &QButtonGroup::idClicked, [](int id){ /* 处理选择 */ });

使用示例

cpp 复制代码
#include <QApplication>
#include <QRadioButton>
#include <QButtonGroup>
#include <QVBoxLayout>
#include <QLabel>
#include <QWidget>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QWidget window;
    window.setWindowTitle("QRadioButton 示例");
    window.resize(300, 250);

    QVBoxLayout *layout = new QVBoxLayout(&window);

    QLabel *label = new QLabel("请选择一种编程语言:");
    layout->addWidget(label);

    // 创建单选按钮
    QRadioButton *radio1 = new QRadioButton("C++");
    QRadioButton *radio2 = new QRadioButton("Python");
    QRadioButton *radio3 = new QRadioButton("Java");
    radio1->setChecked(true);  // 默认选中

    layout->addWidget(radio1);
    layout->addWidget(radio2);
    layout->addWidget(radio3);

    QLabel *result = new QLabel("当前选择:C++");
    layout->addWidget(result);
    layout->addStretch();

    // 使用 QButtonGroup 管理互斥和获取选中项
    QButtonGroup *group = new QButtonGroup(&window);
    group->addButton(radio1, 0);
    group->addButton(radio2, 1);
    group->addButton(radio3, 2);

    QObject::connect(group, QOverload<int>::of(&QButtonGroup::buttonClicked), [&](int id) {
        QString lang;
        switch (id) {
        case 0: lang = "C++";    break;
        case 1: lang = "Python"; break;
        case 2: lang = "Java";   break;
        }
        result->setText("当前选择:" + lang);
    });

    window.show();
    return app.exec();
}

使用效果

Check Box:复选框按钮

支持独立选中/取消,可表示三态。

特性 说明
二态 选中 / 未选中(默认)
三态 setTristate(true) 启用,增加"不确定"状态
信号 stateChanged(int) 状态变化时触发
状态值 Qt::Unchecked(0) / Qt::PartiallyChecked(1) / Qt::Checked(2)
cpp 复制代码
QCheckBox *cb = new QCheckBox("Agree to terms");
cb->setTristate(true);
connect(cb, &QCheckBox::stateChanged, [](int state){
    switch (state) {
    case Qt::Unchecked:        /* 未选中 */ break;
    case Qt::PartiallyChecked: /* 半选 */   break;
    case Qt::Checked:          /* 选中 */   break;
    }
});

使用示例

cpp 复制代码
// ==================== 头文件引入 ====================
#include <QApplication>   // 每个 Qt GUI 程序都必须包含,负责管理应用程序的控制流和设置
#include <QCheckBox>      // 复选框控件,支持二态(勾选/未勾选)和三态(勾选/未勾选/半选)
#include <QVBoxLayout>    // 垂直布局管理器,让控件从上到下依次排列
#include <QLabel>         // 标签控件,用于显示文本或图片(不可编辑)
#include <QWidget>        // 所有可视化控件的基类,这里用作主窗口容器

// ==================== 主函数 ====================
// argc 和 argv 是命令行参数,Qt 程序需要它们来初始化
int main(int argc, char *argv[]) {

    // 创建应用程序对象,整个程序只能有一个 QApplication 实例
    // 它负责处理事件循环、字体、调色板等全局设置
    QApplication app(argc, argv);

    // ==================== 创建主窗口 ====================
    // QWidget 是最基础的窗口类,这里作为顶层窗口使用
    QWidget window;
    window.setWindowTitle("QCheckBox 示例");  // 设置窗口标题栏显示的文字
    window.resize(300, 300);                  // 设置窗口初始大小:宽300像素,高300像素

    // ==================== 布局管理 ====================
    // QVBoxLayout 是垂直盒布局,控件会从上往下依次排列
    // 传入 &window 表示这个布局属于 window 窗口
    // 一旦设置了布局,window 会自动管理布局内所有控件的大小和位置
    QVBoxLayout *layout = new QVBoxLayout(&window);

    // ==================== 创建普通二态复选框 ====================
    // QCheckBox 默认是二态的:只有"勾选"和"未勾选"两种状态
    // 参数是显示在复选框旁边的文字
    QCheckBox *cb1 = new QCheckBox("同意用户协议");
    layout->addWidget(cb1);  // 将控件添加到布局中(自动从上往下排列)

    QCheckBox *cb2 = new QCheckBox("记住密码");
    layout->addWidget(cb2);

    QCheckBox *cb3 = new QCheckBox("自动登录");
    layout->addWidget(cb3);

    // ==================== 创建三态复选框 ====================
    QCheckBox *cbAll = new QCheckBox("全选");
    // setTristate(true) 开启三态模式,三种状态分别是:
    //   Qt::Unchecked   (0) - 未勾选(表示"全不选")
    //   Qt::PartiallyChecked (1) - 半选/中间态(表示"部分选中")
    //   Qt::Checked     (2) - 已勾选(表示"全选")
    cbAll->setTristate(true);
    layout->addWidget(cbAll);

    // ==================== 创建结果标签 ====================
    // 用于实时显示当前勾选了哪些选项
    QLabel *result = new QLabel("已选择:无");
    layout->addWidget(result);

    // addStretch() 在布局末尾添加一个可伸缩的空白区域
    // 它会把上面的所有控件"顶"到窗口顶部,下方留白
    // 如果不加这行,控件会均匀分布在窗口中
    layout->addStretch();

    // ==================== 定义更新函数(Lambda 表达式)====================
    // auto 让编译器自动推导类型,[&] 表示以引用方式捕获外部所有变量
    // 这个 lambda 的作用是:遍历所有复选框,把被勾选的文字拼起来显示到 result 标签上
    auto updateResult = [&]() {
        QStringList selected;  // QStringList 是 Qt 提供的字符串列表,类似 QVector<QString>

        // isChecked() 返回复选框是否被勾选(true/false)
        if (cb1->isChecked()) selected << "同意协议";   // << 是 QStringList 的重载运算符,用于追加元素
        if (cb2->isChecked()) selected << "记住密码";
        if (cb3->isChecked()) selected << "自动登录";

        // isEmpty() 判断列表是否为空
        // join("、") 将列表中所有字符串用 "、" 连接成一个字符串
        result->setText("已选择:" + (selected.isEmpty() ? "无" : selected.join("、")));
    };

    // ==================== 信号与槽连接(核心机制)====================
    // Qt 的核心机制是"信号与槽"(Signals & Slots):
    //   - 信号(signal):控件发出的事件通知,比如按钮被点击、复选框状态改变
    //   - 槽(slot):响应信号的函数,可以是普通函数、成员函数或 lambda 表达式
    //
    // connect 语法:connect(发送者, &类::信号, 接收的函数)
    //
    // toggled 信号:当复选框的勾选状态发生变化时触发,参数是新的勾选状态(bool)
    // 这里三个复选框的状态变化都连接到同一个 updateResult 函数
    QObject::connect(cb1, &QCheckBox::toggled, updateResult);
    QObject::connect(cb2, &QCheckBox::toggled, updateResult);
    QObject::connect(cb3, &QCheckBox::toggled, updateResult);

    // ==================== 全选联动逻辑 ====================
    // stateChanged 信号:当复选框状态发生变化时触发,参数是新的状态值(int)
    // 注意:这里用 stateChanged 而不是 toggled,因为三态复选框有三种状态
    //   toggled 只传 bool(true/false),无法区分"半选"状态
    //   stateChanged 传 int(0=未勾选, 1=半选, 2=已勾选),信息更完整
    QObject::connect(cbAll, &QCheckBox::stateChanged, [&](int state) {
        // Qt::Checked 是枚举值,等于 2,表示"已勾选"状态
        bool checked = (state == Qt::Checked);

        // setChecked() 以编程方式设置复选框的勾选状态
        // 当"全选"被勾选时,三个子项全部勾选;取消勾选时,全部取消
        // 注意:这里只处理了"全选"和"全不选",没有处理"半选"状态
        cb1->setChecked(checked);
        cb2->setChecked(checked);
        cb3->setChecked(checked);
    });

    // ==================== 显示窗口并进入事件循环 ====================
    window.show();       // 默认情况下窗口是隐藏的,必须调用 show() 才会显示
    return app.exec();   // 进入事件循环,程序会一直运行在这里
                         // 直到用户关闭窗口或调用 app.quit() 才会退出
                         // exec() 的返回值就是程序的退出码
}

使用效果

Windows Vista 风格,带有描述文字的链接式按钮。

特性 说明
外观 蓝色文字 + 箭头图标,无传统按钮边框
描述文字 setDescription() 设置副标题说明
图标 setIcon() 可自定义图标
平台 主要在 Windows 上有明显效果,其他平台退化为普通按钮
cpp 复制代码
QCommandLinkButton *cmdBtn = new QCommandLinkButton("Install Update");
cmdBtn->setDescription("Download and install the latest version.");
cmdBtn->setIcon(QIcon(":/icons/update.png"));
connect(cmdBtn, &QCommandLinkButton::clicked, [](){ /* 处理点击 */ });

使用示例

cpp 复制代码
#include <QApplication>
#include <QCommandLinkButton>
#include <QVBoxLayout>
#include <QLabel>
#include <QWidget>
#include <QMessageBox>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QWidget window;
    window.setWindowTitle("QCommandLinkButton 示例");
    window.resize(400, 350);

    QVBoxLayout *layout = new QVBoxLayout(&window);

    QLabel *title = new QLabel("<h2>请选择操作:</h2>");
    layout->addWidget(title);

    // 命令链接按钮1
    QCommandLinkButton *cmd1 = new QCommandLinkButton("安装更新");
    cmd1->setDescription("下载并安装最新版本的应用程序。");
    layout->addWidget(cmd1);

    // 命令链接按钮2
    QCommandLinkButton *cmd2 = new QCommandLinkButton("修复系统");
    cmd2->setDescription("扫描并修复系统中的已知问题。");
    layout->addWidget(cmd2);

    // 命令链接按钮3
    QCommandLinkButton *cmd3 = new QCommandLinkButton("查看帮助");
    cmd3->setDescription("打开用户手册和常见问题解答。");
    layout->addWidget(cmd3);

    layout->addStretch();

    QObject::connect(cmd1, &QCommandLinkButton::clicked, [&]() {
        QMessageBox::information(&window, "安装更新", "正在检查更新...");
    });
    QObject::connect(cmd2, &QCommandLinkButton::clicked, [&]() {
        QMessageBox::information(&window, "修复系统", "正在扫描系统...");
    });
    QObject::connect(cmd3, &QCommandLinkButton::clicked, [&]() {
        QMessageBox::information(&window, "帮助", "正在打开帮助文档...");
    });

    window.show();
    return app.exec();
}

示例效果

QDialogButtonBox按钮盒

对话框专用容器,自动排列标准按钮并处理角色。

特性 说明
标准按钮 一键添加 OK、Cancel、Yes、No 等预定义按钮
角色管理 每个按钮自动分配角色(Accept / Reject / Action 等)
信号转发 accepted() / rejected() 信号自动关联
布局方向 setOrientation() 水平或垂直排列

ButtonRole 枚举值:

说明
QDialogButtonBox::AcceptRole 接受(如 OK)
QDialogButtonBox::RejectRole 拒绝(如 Cancel)
QDialogButtonBox::DestructiveRole 破坏性操作(如 Discard)
QDialogButtonBox::HelpRole 帮助
QDialogButtonBox::ActionRole 自定义动作
QDialogButtonBox::ResetRole 重置
QDialogButtonBox::ApplyRole 应用

StandardButton 常用值:

角色
QDialogButtonBox::Ok AcceptRole
QDialogButtonBox::Cancel RejectRole
QDialogButtonBox::Yes AcceptRole
QDialogButtonBox::No RejectRole
QDialogButtonBox::Apply ApplyRole
QDialogButtonBox::Close RejectRole
QDialogButtonBox::Save AcceptRole
QDialogButtonBox::Discard DestructiveRole
cpp 复制代码
QDialogButtonBox *btnBox = new QDialogButtonBox(
    QDialogButtonBox::Ok | QDialogButtonBox::Cancel, parent);

connect(btnBox, &QDialogButtonBox::accepted, dialog, &QDialog::accept);
connect(btnBox, &QDialogButtonBox::rejected, dialog, &QDialog::reject);

// 动态添加自定义按钮
QPushButton *customBtn = btnBox->addButton("Custom", QDialogButtonBox::ActionRole);

示例代码

cpp 复制代码
#include <QApplication>
#include <QDialog>
#include <QDialogButtonBox>
#include <QVBoxLayout>
#include <QLabel>
#include <QMessageBox>
#include <QPushButton>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    QDialog dialog;
    dialog.setWindowTitle("QDialogButtonBox 示例");
    dialog.resize(350, 200);

    QVBoxLayout *layout = new QVBoxLayout(&dialog);

    QLabel *label = new QLabel("确定要保存更改吗?\n未保存的更改将会丢失。");
    layout->addWidget(label);

    // 创建标准按钮盒:Save / Discard / Cancel
    QDialogButtonBox *btnBox = new QDialogButtonBox(
        QDialogButtonBox::Save |
        QDialogButtonBox::Discard |
        QDialogButtonBox::Cancel,
        &dialog
    );
    layout->addWidget(btnBox);

    // 连接标准信号
    QObject::connect(btnBox, &QDialogButtonBox::accepted, [&]() {
        QMessageBox::information(&dialog, "结果", "你点击了【保存】");
        dialog.accept();
    });

    QObject::connect(btnBox, &QDialogButtonBox::rejected, [&]() {
        QMessageBox::information(&dialog, "结果", "你点击了【取消】");
        dialog.reject();
    });

    // 单独处理 Discard 按钮
    QPushButton *discardBtn = btnBox->button(QDialogButtonBox::Discard);
    QObject::connect(discardBtn, &QPushButton::clicked, [&]() {
        QMessageBox::information(&dialog, "结果", "你点击了【放弃】");
        dialog.reject();
    });

    dialog.exec();
    return app.exec();
}

示例效果

容器组控件

Group Box:

QGroupBox 是一个带标题的分组容器,用于在视觉上将一组相关的控件归为一类,让界面更清晰、更有层次感。

常用 API

函数 说明
setTitle(const QString &) 设置分组框标题
title() 获取标题文本
setCheckable(bool) 设置是否可勾选(勾选后内部控件才启用)
isChecked() 获取勾选状态
setChecked(bool) 设置勾选状态
isFlat() 是否以扁平样式显示(无边框)
setFlat(bool) 设置扁平样式

使用示例

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QGroupBox>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QSpinBox>
#include <QCheckBox>
#include <QPushButton>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // ====== 创建一个中心控件 ======
    QWidget *centralWidget = new QWidget(this);
    setCentralWidget(centralWidget);

    QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);

    // ====== 分组框1:用户信息 ======
    QGroupBox *userGroup = new QGroupBox("用户信息", this);
    QVBoxLayout *userLayout = new QVBoxLayout(userGroup);
    userLayout->addWidget(new QLabel("姓名:"));
    userLayout->addWidget(new QLineEdit);
    userLayout->addWidget(new QLabel("年龄:"));
    userLayout->addWidget(new QSpinBox);
    mainLayout->addWidget(userGroup);

    // ====== 分组框2:可勾选的高级选项 ======
    QGroupBox *advGroup = new QGroupBox("高级选项", this);
    advGroup->setCheckable(true);   // 标题前出现勾选框
    advGroup->setChecked(false);    // 默认不勾选,内部控件禁用
    QVBoxLayout *advLayout = new QVBoxLayout(advGroup);
    advLayout->addWidget(new QCheckBox("启用日志"));
    advLayout->addWidget(new QCheckBox("自动保存"));
    advLayout->addWidget(new QPushButton("导出配置"));
    mainLayout->addWidget(advGroup);

    // ====== 分组框3:扁平样式 ======
    QGroupBox *flatGroup = new QGroupBox("只保留标题", this);
    flatGroup->setFlat(true);       // 无边框,只显示标题
    QVBoxLayout *flatLayout = new QVBoxLayout(flatGroup);
    flatLayout->addWidget(new QLabel("这是一个扁平样式的分组框"));
    mainLayout->addWidget(flatGroup);

    // 底部按钮
    QPushButton *submitBtn = new QPushButton("提交");
    mainLayout->addWidget(submitBtn);
}

MainWindow::~MainWindow()
{
    delete ui;
}

使用效果

ScrollArea:滚动区域

QScrollArea 是一个带滚动条的容器控件,当内部内容超出可视区域时,自动出现滚动条,让用户可以滚动查看所有内容。QScrollArea 本身不能直接添加多个控件,它只能容纳一个子控件(Widget)。如果要在里面放多个控件,需要:

创建一个容器 QWidget

给容器设置布局,往布局里添加各种控件

把这个容器通过 setWidget() 放进 QScrollArea

cpp 复制代码
QScrollArea(滚动区域)
└── QWidget(容器,唯一子控件)
    └── QVBoxLayout(布局)
        ├── QLabel
        ├── QPushButton
        ├── QLabel
        └── ...(任意多个控件)

滚动条策略有三种

策略 说明
Qt::ScrollBarAsNeeded 需要时才显示(默认)
Qt::ScrollBarAlwaysOn 始终显示
Qt::ScrollBarAlwaysOff 始终隐藏

使用实例

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QScrollArea>
#include <QVBoxLayout>
#include <QLabel>
#include <QPushButton>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 创建滚动区域
    QScrollArea *scrollArea = new QScrollArea(this);
    scrollArea->setWidgetResizable(true);

    // 创建容器
    QWidget *container = new QWidget;
    QVBoxLayout *layout = new QVBoxLayout(container);

    // 添加大量内容
    for (int i = 1; i <= 50; i++) {
        QLabel *label = new QLabel(QString("第 %1 行内容").arg(i));
        layout->addWidget(label);
    }

    scrollArea->setWidget(container);
    setCentralWidget(scrollArea);
}

MainWindow::~MainWindow()
{
    delete ui;
}

效果

Tool Box:工具箱

QToolBox 是一个垂直堆叠的可折叠面板控件,每个面板有一个标题栏,点击标题可以展开/折叠对应内容,同一时刻只有一个面板处于展开状态。常用于实现类似"设置面板"、"属性编辑器"等界面。

使用示例

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QToolBox>
#include <QVBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QComboBox>
#include <QSpinBox>
#include <QCheckBox>
#include <QPushButton>
#include <QGroupBox>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setWindowTitle("QToolBox 工具箱示例");
    resize(350, 500);

    // 创建 QToolBox
    QToolBox *toolBox = new QToolBox(this);

    // ====== 页面1:基本设置 ======
    QWidget *page1 = new QWidget;
    QVBoxLayout *layout1 = new QVBoxLayout(page1);
    layout1->addWidget(new QLabel("字体:"));
    QComboBox *fontCombo = new QComboBox;
    fontCombo->addItems({"宋体", "微软雅黑", "楷体", "黑体"});
    layout1->addWidget(fontCombo);
    layout1->addWidget(new QLabel("字号:"));
    QSpinBox *sizeSpin = new QSpinBox;
    sizeSpin->setRange(8, 72);
    sizeSpin->setValue(12);
    layout1->addWidget(sizeSpin);
    layout1->addStretch();  // 底部弹簧,控件靠上对齐

    // ====== 页面2:高级设置 ======
    QWidget *page2 = new QWidget;
    QVBoxLayout *layout2 = new QVBoxLayout(page2);
    layout2->addWidget(new QCheckBox("启用调试模式"));
    layout2->addWidget(new QCheckBox("启用日志记录"));
    layout2->addWidget(new QCheckBox("自动保存"));
    layout2->addWidget(new QCheckBox("启动时检查更新"));
    layout2->addStretch();

    // ====== 页面3:外观设置 ======
    QWidget *page3 = new QWidget;
    QVBoxLayout *layout3 = new QVBoxLayout(page3);
    layout3->addWidget(new QLabel("主题:"));
    QComboBox *themeCombo = new QComboBox;
    themeCombo->addItems({"浅色", "深色", "跟随系统"});
    layout3->addWidget(themeCombo);
    layout3->addWidget(new QLabel("透明度:"));
    QSpinBox *opacitySpin = new QSpinBox;
    opacitySpin->setRange(50, 100);
    opacitySpin->setValue(100);
    opacitySpin->setSuffix("%");
    layout3->addWidget(opacitySpin);
    layout3->addStretch();

    // ====== 页面4:关于 ======
    QWidget *page4 = new QWidget;
    QVBoxLayout *layout4 = new QVBoxLayout(page4);
    QLabel *aboutLabel = new QLabel("QToolBox 示例程序\n版本:1.0.0\n作者:Qt 学习者");
    aboutLabel->setAlignment(Qt::AlignCenter);
    layout4->addWidget(aboutLabel);
    QPushButton *btn = new QPushButton("确定");
    layout4->addWidget(btn, 0, Qt::AlignCenter);
    layout4->addStretch();

    // 将页面添加到 QToolBox
    toolBox->addItem(page1, "基本设置");
    toolBox->addItem(page2, "高级设置");
    toolBox->addItem(page3, "外观设置");
    toolBox->addItem(page4, "关于");

    // 默认展开第一个页面
    toolBox->setCurrentIndex(0);

    setCentralWidget(toolBox);

    // 连接信号:切换页面时输出当前页面标题
    connect(toolBox, &QToolBox::currentChanged, [toolBox](int index) {
        qDebug() << "切换到页面:" << toolBox->itemText(index);
    });
}

MainWindow::~MainWindow()
{
    delete ui;
}

示例效果

Tab Widget:标签小部件

cpp 复制代码
#include <QApplication>
#include <QTabWidget>
#include <QLabel>
#include <QLineEdit>
#include <QVBoxLayout>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QTabWidget *tabWidget = new QTabWidget;
    tabWidget->resize(350, 250);
    tabWidget->setWindowTitle("Tab Widget 示例");

    // 标签页1:基本信息
    QWidget *page1 = new QWidget;
    QVBoxLayout *layout1 = new QVBoxLayout(page1);
    layout1->addWidget(new QLabel("姓名:"));
    layout1->addWidget(new QLineEdit);
    layout1->addWidget(new QLabel("年龄:"));
    layout1->addWidget(new QLineEdit);

    // 标签页2:关于
    QWidget *page2 = new QWidget;
    QVBoxLayout *layout2 = new QVBoxLayout(page2);
    layout2->addWidget(new QLabel("这是一个简单的 Tab Widget 示例"));
    layout2->addWidget(new QLabel("版本:1.0"));

    // 添加标签页
    tabWidget->addTab(page1, "基本信息");
    tabWidget->addTab(page2, "关于");

    tabWidget->show();
    return a.exec();
}

Frama 框架

QFrame 是一个基础的框架控件,用于在界面上绘制各种边框、分隔线、面板等装饰性元素,也可以作为容器承载其他控件。

典型示例

cpp 复制代码
#include <QApplication>      // Qt应用程序类,管理程序的控制流和设置
#include <QFrame>            // 框架控件,可做分隔线或带边框的容器
#include <QLabel>            // 标签控件,用于显示文本或图片
#include <QLineEdit>         // 单行输入框
#include <QPushButton>       // 按钮控件
#include <QVBoxLayout>       // 垂直布局,控件从上到下排列
#include <QMessageBox>       // 消息弹窗(提示框、警告框等)

int main(int argc, char *argv[])
{
    // 创建Qt应用程序对象,每个Qt程序有且只有一个
    QApplication a(argc, argv);

    // 创建主窗口
    QWidget window;
    window.resize(400, 350);                              // 设置窗口大小:宽400,高350
    window.setWindowTitle("QFrame 卡片示例");             // 设置窗口标题
    window.setStyleSheet("background-color: #f0f0f0;");   // 设置窗口背景为浅灰色

    // 创建主布局(垂直排列),绑定到window上
    QVBoxLayout *mainLayout = new QVBoxLayout(&window);
    mainLayout->setAlignment(Qt::AlignCenter);            // 布局内容居中对齐

    // ========== 核心:用 QFrame 做卡片容器 ==========
    QFrame *card = new QFrame;
    // 用样式表设置卡片外观:白色背景、浅灰边框、圆角10px
    card->setStyleSheet(
        "QFrame {"
        "  background-color: white;"
        "  border: 1px solid #ddd;"
        "  border-radius: 10px;"
        "}"
    );
    card->setFixedWidth(320);  // 卡片固定宽度320,高度随内容自适应

    // 给卡片内部创建垂直布局,间距15px,四边内边距30px
    QVBoxLayout *cardLayout = new QVBoxLayout(card);
    cardLayout->setSpacing(15);
    cardLayout->setContentsMargins(30, 30, 30, 30);  // 上、左、下、右各留30px

    // ---- 标题 ----
    QLabel *title = new QLabel("用户登录");
    title->setAlignment(Qt::AlignCenter);                          // 文字居中
    title->setStyleSheet("font-size: 20px; font-weight: bold; border: none;");  // 大号加粗,去掉继承的边框
    cardLayout->addWidget(title);

    // ---- 分隔线(QFrame 第二常用场景) ----
    QFrame *line = new QFrame;
    line->setFrameShape(QFrame::HLine);      // 设置为水平线
    line->setFrameShadow(QFrame::Sunken);    // 凹陷效果(看起来有立体感)
    line->setStyleSheet("border: none; border-top: 1px solid #eee;");  // 自定义为1px浅灰线
    cardLayout->addWidget(line);

    // ---- 用户名输入框 ----
    QLineEdit *userEdit = new QLineEdit;
    userEdit->setPlaceholderText("请输入用户名");   // 占位提示文字(输入后消失)
    userEdit->setMinimumHeight(35);                 // 最小高度35px,让输入框大一点
    cardLayout->addWidget(userEdit);

    // ---- 密码输入框 ----
    QLineEdit *passEdit = new QLineEdit;
    passEdit->setPlaceholderText("请输入密码");
    passEdit->setEchoMode(QLineEdit::Password);     // 密码模式,输入内容显示为圆点
    passEdit->setMinimumHeight(35);
    cardLayout->addWidget(passEdit);

    // ---- 登录按钮 ----
    QPushButton *loginBtn = new QPushButton("登 录");
    loginBtn->setMinimumHeight(38);                 // 按钮最小高度
    loginBtn->setStyleSheet(
        "QPushButton {"
        "  background-color: #4CAF50;"              // 绿色背景
        "  color: white;"                           // 白色文字
        "  border: none;"                           // 无边框
        "  border-radius: 5px;"                     // 圆角5px
        "  font-size: 15px;"                        // 字号15px
        "}"
        "QPushButton:hover { background-color: #45a049; }"  // 鼠标悬停时颜色变深
    );
    cardLayout->addWidget(loginBtn);

    // 将卡片添加到主布局中,居中对齐
    mainLayout->addWidget(card, 0, Qt::AlignCenter);

    // ---- 点击登录按钮的事件处理 ----
    QObject::connect(loginBtn, &QPushButton::clicked, [&]() {
        QString user = userEdit->text();    // 获取用户名输入内容
        QString pass = passEdit->text();    // 获取密码输入内容
        if (user.isEmpty() || pass.isEmpty()) {
            // 任一为空,弹出警告框
            QMessageBox::warning(&window, "提示", "用户名和密码不能为空!");
        } else {
            // 都不为空,弹出欢迎信息
            QMessageBox::information(&window, "成功", "欢迎," + user + "!");
        }
    });

    window.show();       // 显示主窗口
    return a.exec();     // 进入事件循环,程序在此阻塞等待用户操作
}

示例效果

Dock Widget:停靠窗体部件

QDockWidget 是一个可停靠的浮动面板,可以停靠在主窗口的上、下、左、右四个方向,也可以脱离主窗口变成独立浮动窗口,甚至可以在多个停靠区域之间自由拖拽。常见于 IDE、图像处理软件等专业工具界面。

特性 说明
停靠方向 可停靠在主窗口的上、下、左、右
浮动 可脱离主窗口变成独立窗口
可关闭 标题栏有关闭按钮(可禁用)
可移动 可在停靠区域之间拖拽
嵌套停靠 多个 DockWidget 可以堆叠在一起,通过 Tab 切换

使用示例

cpp 复制代码
#include <QApplication>      // Qt应用程序类,管理程序的控制流和设置,每个Qt程序有且只有一个
#include <QMainWindow>       // 主窗口类,自带菜单栏、工具栏、状态栏、停靠窗口的支持
#include <QDockWidget>       // 停靠窗口控件,可以拖拽、浮动、停靠在主窗口的四周
#include <QTextEdit>         // 多行文本编辑控件
#include <QTreeWidget>       // 树形控件,用于显示层级结构数据(如文件目录)
#include <QLabel>            // 标签控件,用于显示文本或图片
#include <QMenuBar>          // 菜单栏
#include <QStatusBar>        // 状态栏,显示在主窗口底部

int main(int argc, char *argv[])
{
    // 创建Qt应用程序对象,管理程序的控制流和设置
    QApplication a(argc, argv);

    // ========== 创建主窗口 ==========
    QMainWindow window;
    window.resize(800, 500);                    // 设置窗口大小:宽800,高500
    window.setWindowTitle("QDockWidget 示例");  // 设置窗口标题栏文字

    // ========== 主区域:文本编辑器 ==========
    // QMainWindow 的中心区域只能放一个控件,这里放一个多行文本编辑器
    QTextEdit *editor = new QTextEdit;
    editor->setPlaceholderText("这里是主编辑区域...");  // 占位提示文字(内容为空时显示)
    window.setCentralWidget(editor);                    // 设置为中心控件,占据主窗口中间区域

    // ========== 左侧停靠窗口:项目树 ==========
    // 创建一个停靠窗口,标题为"项目",父窗口为window
    QDockWidget *projectDock = new QDockWidget("项目", &window);
    // 限制停靠位置:只允许停靠在主窗口的左侧或右侧
    // Qt::LeftDockWidgetArea  = 左侧区域
    // Qt::RightDockWidgetArea = 右侧区域
    // 用 | 组合表示两个位置都允许
    projectDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);

    // 创建树形控件,用来显示文件目录结构
    QTreeWidget *tree = new QTreeWidget;
    tree->setHeaderLabel("文件");  // 设置树形控件的列标题为"文件"

    // 添加第一层节点 "src",然后给它添加3个子节点
    tree->addTopLevelItem(new QTreeWidgetItem({"src"}));           // 顶层节点:src
    tree->topLevelItem(0)->addChild(new QTreeWidgetItem({"main.cpp"}));    // src 的子节点
    tree->topLevelItem(0)->addChild(new QTreeWidgetItem({"widget.cpp"}));  // src 的子节点
    tree->topLevelItem(0)->addChild(new QTreeWidgetItem({"widget.h"}));    // src 的子节点

    // 添加第二层节点 "include",然后给它添加1个子节点
    tree->addTopLevelItem(new QTreeWidgetItem({"include"}));       // 顶层节点:include
    tree->topLevelItem(1)->addChild(new QTreeWidgetItem({"global.h"}));    // include 的子节点

    tree->expandAll();  // 展开所有节点(默认是折叠的)

    // 把树形控件设置为停靠窗口的内容
    projectDock->setWidget(tree);
    // 把停靠窗口添加到主窗口的左侧区域
    window.addDockWidget(Qt::LeftDockWidgetArea, projectDock);

    // ========== 右侧停靠窗口:属性面板 ==========
    QDockWidget *propertyDock = new QDockWidget("属性", &window);
    // 同样只允许停靠在左右两侧
    propertyDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);

    // 用 QLabel 显示属性信息(实际项目中会用 QPropertyEditor 等更复杂的控件)
    QLabel *propertyLabel = new QLabel("选中对象后显示属性\n\n名称:widget\n宽度:400\n高度:300\n可见:true");
    propertyLabel->setAlignment(Qt::AlignTop);           // 文字靠顶部对齐(默认是居中)
    propertyLabel->setContentsMargins(10, 10, 10, 10);   // 四边内边距各10px,避免文字贴边

    propertyDock->setWidget(propertyLabel);              // 把标签放进停靠窗口
    window.addDockWidget(Qt::RightDockWidgetArea, propertyDock);  // 停靠到主窗口右侧

    // ========== 底部停靠窗口:输出窗口 ==========
    QDockWidget *outputDock = new QDockWidget("输出", &window);
    // 只允许停靠在顶部或底部(上下方向)
    outputDock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);

    // 创建一个只读的文本编辑控件,用来显示编译输出信息
    QTextEdit *output = new QTextEdit;
    output->setReadOnly(true);  // 设为只读,用户不能编辑
    // 逐行添加输出信息
    output->append("构建开始...");
    output->append("编译 main.cpp ... 成功");
    output->append("编译 widget.cpp ... 成功");
    output->append("链接 ... 成功");
    output->append("构建完成,耗时 2.3s");

    outputDock->setWidget(output);                               // 把输出控件放进停靠窗口
    window.addDockWidget(Qt::BottomDockWidgetArea, outputDock);   // 停靠到主窗口底部

    // ========== 菜单栏:控制停靠窗口的显示/隐藏 ==========
    // 在菜单栏添加一个"视图"菜单
    QMenu *viewMenu = window.menuBar()->addMenu("视图");
    // toggleViewAction() 是 QDockWidget 自带的 Action:
    //   - 自动生成一个带勾选框的菜单项
    //   - 勾选 = 显示停靠窗口,取消勾选 = 隐藏停靠窗口
    //   - 不需要自己写信号槽,Qt自动处理
    viewMenu->addAction(projectDock->toggleViewAction());    // 添加"项目"的显示/隐藏菜单项
    viewMenu->addAction(propertyDock->toggleViewAction());   // 添加"属性"的显示/隐藏菜单项
    viewMenu->addAction(outputDock->toggleViewAction());     // 添加"输出"的显示/隐藏菜单项

    // ========== 状态栏 ==========
    // 在主窗口底部状态栏显示"就绪"文字
    window.statusBar()->showMessage("就绪");

    window.show();       // 显示主窗口
    return a.exec();     // 进入事件循环,程序在此阻塞等待用户操作(关闭窗口后退出)
}

使用效果

item View 列表控件

QListView

cpp 复制代码
#include <QApplication>
#include <QListView>
#include <QStringListModel>
#include <QLineEdit>
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QComboBox>
#include <QCheckBox>
#include <QMessageBox>
#include <QItemSelectionModel>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QWidget window;
    window.resize(500, 550);
    window.setWindowTitle("QListView 经典示例(Model/View 架构)");

    QVBoxLayout *mainLayout = new QVBoxLayout(&window);

    // ============================================================
    // 1. 创建数据模型(Model)
    //    QStringListModel 是 Qt 提供的最简单的字符串列表模型
    //    QListView 本身不存储数据,所有数据由 Model 管理
    // ============================================================
    QStringListModel *model = new QStringListModel;

    // 准备初始数据
    QStringList dataList;
    dataList << "C++" << "Python" << "Java" << "JavaScript"
             << "Go" << "Rust" << "TypeScript" << "Kotlin"
             << "Swift" << "Ruby";
    model->setStringList(dataList);  // 将数据设置到模型中

    // ============================================================
    // 2. 创建 QListView 控件,并绑定模型
    // ============================================================
    QListView *listView = new QListView;
    listView->setModel(model);  // 核心:把模型绑定到视图上
    // 此后视图会自动从模型中读取数据并显示

    // --- 视图外观设置 ---
    listView->setAlternatingRowColors(true);  // 交替行颜色,方便阅读
    listView->setSpacing(2);                  // 每项之间的间距(像素)
    listView->setEditTriggers(QAbstractItemView::DoubleClicked |
                              QAbstractItemView::SelectedClicked);  // 双击或单击已选中项可编辑
    listView->setSelectionMode(QAbstractItemView::ExtendedSelection);  // Ctrl/Shift 多选

    mainLayout->addWidget(new QLabel("编程语言列表(双击可编辑):"));
    mainLayout->addWidget(listView);

    // ============================================================
    // 3. 操作区域:增删改查
    // ============================================================
    QHBoxLayout *opLayout = new QHBoxLayout;

    QLineEdit *input = new QLineEdit;
    input->setPlaceholderText("输入新语言名称...");

    QPushButton *addBtn    = new QPushButton("添加");
    QPushButton *insertBtn = new QPushButton("插入到当前位置");
    QPushButton *deleteBtn = new QPushButton("删除选中");
    QPushButton *clearBtn  = new QPushButton("清空全部");

    opLayout->addWidget(input);
    opLayout->addWidget(addBtn);
    opLayout->addWidget(insertBtn);
    opLayout->addWidget(deleteBtn);
    opLayout->addWidget(clearBtn);
    mainLayout->addLayout(opLayout);

    // ============================================================
    // 4. 排序与显示方向控制
    // ============================================================
    QHBoxLayout *settingLayout = new QHBoxLayout;

    QPushButton *sortAscBtn  = new QPushButton("升序排序");
    QPushButton *sortDescBtn = new QPushButton("降序排序");
    QCheckBox *flowCheck     = new QCheckBox("横向排列");
    QComboBox *layoutCombo   = new QComboBox;
    layoutCombo->addItems({"列表模式(ListMode)", "图标模式(IconMode)"});

    settingLayout->addWidget(sortAscBtn);
    settingLayout->addWidget(sortDescBtn);
    settingLayout->addWidget(flowCheck);
    settingLayout->addWidget(layoutCombo);
    mainLayout->addLayout(settingLayout);

    // ============================================================
    // 5. 底部信息栏
    // ============================================================
    QLabel *infoLabel = new QLabel("共 0 项 | 未选中");
    infoLabel->setStyleSheet("color: #555; padding: 5px; background: #f0f0f0; border-radius: 3px;");
    mainLayout->addWidget(infoLabel);

    // ============================================================
    // 6. 更新信息栏的 Lambda
    // ============================================================
    auto updateInfo = [&]() {
        int total = model->rowCount();  // 从模型获取总行数
        QModelIndexList selected = listView->selectionModel()->selectedIndexes();  // 获取选中项的索引列表
        int selectedCount = selected.size();

        QString text = QString("共 %1 项").arg(total);
        if (selectedCount > 0) {
            // 取第一个选中项的文本
            QString firstText = selected.first().data(Qt::DisplayRole).toString();
            text += QString(" | 已选中 %1 项(当前:%2)").arg(selectedCount).arg(firstText);
        } else {
            text += " | 未选中";
        }
        infoLabel->setText(text);
    };

    // ============================================================
    // 7. 信号槽连接
    // ============================================================

    // --- 添加:追加到末尾 ---
    QObject::connect(addBtn, &QPushButton::clicked, [&]() {
        QString text = input->text().trimmed();
        if (text.isEmpty()) {
            QMessageBox::warning(&window, "提示", "请输入内容!");
            return;
        }
        // 通过模型操作数据(不是直接操作视图)
        int row = model->rowCount();  // 当前行数 = 新项的插入位置
        model->insertRow(row);        // 在末尾插入一行
        model->setData(model->index(row), text);  // 设置该行显示的数据
        input->clear();
        input->setFocus();
        updateInfo();
    });

    // --- 插入到当前选中位置的上方 ---
    QObject::connect(insertBtn, &QPushButton::clicked, [&]() {
        QString text = input->text().trimmed();
        if (text.isEmpty()) {
            QMessageBox::warning(&window, "提示", "请输入内容!");
            return;
        }
        // 获取当前选中行的行号,如果没有选中则插入到末尾
        int row = model->rowCount();
        QModelIndex currentIndex = listView->currentIndex();
        if (currentIndex.isValid()) {
            row = currentIndex.row();  // 在选中项的位置插入
        }
        model->insertRow(row);
        model->setData(model->index(row), text);
        // 选中新插入的项
        listView->setCurrentIndex(model->index(row));
        input->clear();
        input->setFocus();
        updateInfo();
    });

    // --- 删除选中项 ---
    QObject::connect(deleteBtn, &QPushButton::clicked, [&]() {
        QModelIndexList selected = listView->selectionModel()->selectedIndexes();
        if (selected.isEmpty()) {
            QMessageBox::warning(&window, "提示", "请先选中要删除的项!");
            return;
        }
        // 从后往前删除,避免行号偏移导致删错
        // 先按行号降序排序
        std::sort(selected.begin(), selected.end(),
                  [](const QModelIndex &a, const QModelIndex &b) {
                      return a.row() > b.row();
                  });
        for (const QModelIndex &idx : selected) {
            model->removeRow(idx.row());  // 通过模型删除行
        }
        updateInfo();
    });

    // --- 清空全部 ---
    QObject::connect(clearBtn, &QPushButton::clicked, [&]() {
        model->removeRows(0, model->rowCount());  // 从第0行开始,删除所有行
        updateInfo();
    });

    // --- 升序排序 ---
    QObject::connect(sortAscBtn, &QPushButton::clicked, [&]() {
        model->sort(0, Qt::AscendingOrder);   // 第0列,升序
    });

    // --- 降序排序 ---
    QObject::connect(sortDescBtn, &QPushButton::clicked, [&]() {
        model->sort(0, Qt::DescendingOrder);  // 第0列,降序
    });

    // --- 横向/纵向排列切换 ---
    QObject::connect(flowCheck, &QCheckBox::toggled, [&](bool checked) {
        if (checked) {
            listView->setFlow(QListView::LeftToRight);   // 横向排列
            listView->setWrapping(true);                  // 允许换行
            listView->setResizeMode(QListView::Adjust);   // 自动调整大小
            listView->setSpacing(10);
        } else {
            listView->setFlow(QListView::TopToBottom);   // 纵向排列(默认)
            listView->setWrapping(false);
            listView->setResizeMode(QListView::Fixed);
            listView->setSpacing(2);
        }
    });

    // --- 列表模式 / 图标模式 切换 ---
    QObject::connect(layoutCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), [&](int index) {
        if (index == 0) {
            listView->setViewMode(QListView::ListMode);   // 列表模式:紧凑排列
        } else {
            listView->setViewMode(QListView::IconMode);   // 图标模式:网格排列,可拖拽
            listView->setMovement(QListView::Snap);       // 对齐到网格
        }
    });

    // --- 数据变化时自动更新信息栏 ---
    QObject::connect(model, &QStringListModel::dataChanged, updateInfo);
    QObject::connect(listView->selectionModel(),
                     &QItemSelectionModel::selectionChanged,
                     updateInfo);

    // 初始化信息
    updateInfo();

    window.show();
    return a.exec();
}

table View

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QStandardItemModel>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // 调用自定义函数
    InitTableViewFunc();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::InitTableViewFunc(){
    // 添加表头,准备数据模型
    QStandardItemModel *stuMode = new QStandardItemModel();
    stuMode->setHorizontalHeaderItem(0,new QStandardItem(QObject::tr("学号")));
    stuMode->setHorizontalHeaderItem(1,new QStandardItem(QObject::tr("姓名")));
    stuMode->setHorizontalHeaderItem(2,new QStandardItem(QObject::tr("性别")));
    stuMode->setHorizontalHeaderItem(3,new QStandardItem(QObject::tr("分数")));

    // 通过API函数将数据模型绑定到QTableCiew
    ui->tableView->setModel(stuMode);

    // 设置表格列的宽度
    ui->tableView->setColumnWidth(0,120);

    // 添加数据信息
    stuMode->setItem(0,0,new QStandardItem("2022001"));
    stuMode->setItem(0,1,new QStandardItem("吴用"));
    stuMode->setItem(0,2,new QStandardItem("男"));
    stuMode->setItem(0,3,new QStandardItem("688"));


    stuMode->setItem(1,0,new QStandardItem("2022002"));
    stuMode->setItem(1,1,new QStandardItem("吴可2"));
    stuMode->setItem(1,2,new QStandardItem("女2"));
    stuMode->setItem(1,3,new QStandardItem("682"));
    stuMode->sort(3,Qt::DescendingOrder);
}

list Widget 清单控件

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QListWidget>
#include <QListWidgetItem>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QListWidgetItem *qitem = new QListWidgetItem("沁园春雪 作者:毛泽东");
    ui->listWidget->addItem(qitem);
    qitem->setTextAlignment(Qt::AlignCenter);
    QStringList slist;
    slist<<"北国风光,千里冰封,万里雪飘。";
    slist<<"望长城内外,惟余莽莽;大河上下,顿失滔滔。";
    slist<<"山舞银蛇,原驰蜡象,欲与天公试比高。";
    ui->listWidget->addItems(slist);
}

Widget::~Widget()
{
    delete ui;
}

tree Widget 树形控件

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 添加第一级节点
    QTreeWidgetItem *topItem1 = new QTreeWidgetItem(ui->treeWidget);
    topItem1->setText(0,"清华大学");
    topItem1->setCheckState(0,Qt::Checked);
    ui->treeWidget->addTopLevelItem(topItem1);

    // 隐藏表头
    ui->treeWidget->setHeaderHidden(true);
    ui->treeWidget->expandAll();

    // 将二级节点添加到一级节点的topitem1
    QTreeWidgetItem *topItem11 = new QTreeWidgetItem(topItem1);
    topItem11->setText(0,"建筑学院");
    topItem11->setCheckState(0,Qt::Checked);


    QTreeWidgetItem *topItem12 = new QTreeWidgetItem(topItem1);
    topItem12->setText(0,"计算机");
    topItem12->setCheckState(0,Qt::Checked);


    QTreeWidgetItem *topItem13 = new QTreeWidgetItem(topItem1);
    topItem13->setText(0,"美术");
    topItem13->setCheckState(0,Qt::Checked);


    QTreeWidgetItem *topItem14 = new QTreeWidgetItem(topItem1);
    topItem14->setText(0,"信息科学与技术");
    topItem14->setCheckState(0,Qt::Checked);


    QTreeWidgetItem *topItem2 = new QTreeWidgetItem(ui->treeWidget);
    topItem2->setText(0,"背景大学");
    topItem2->setCheckState(0,Qt::Checked);
    ui->treeWidget->addTopLevelItem(topItem2);



    QTreeWidgetItem *topItem21 = new QTreeWidgetItem(topItem2);
    topItem21->setText(0,"美术学院");
    topItem21->setCheckState(0,Qt::Checked);


    QTreeWidgetItem *topItem22 = new QTreeWidgetItem(topItem2);
    topItem22->setText(0,"信息科学与技术");
    topItem22->setCheckState(0,Qt::Checked);
}

Widget::~Widget()
{
    delete ui;
}

table Widget 表控件

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 设置表格行数和列数
    ui->tableWidget->setRowCount(3);
    ui->tableWidget->setColumnCount(2);

    // 设置水平表头
    QStringList slist;
    slist<<"学号"<<"高考分数";
    ui->tableWidget->setHorizontalHeaderLabels(slist);

    QList<QString> strno;
    strno<<"202201"<<"202202"<<"202203";


    QList<QString> strscore;
    strscore<<"708"<<"688"<<"712";

    // 通过循环为表格赋值
    for(int i=0;i<3;i++){
        int icol =0;
        QTableWidgetItem *pitem = new QTableWidgetItem(strno.at(i));
        ui->tableWidget->setItem(i,icol++,pitem);
        ui->tableWidget->setItem(i,icol++,new QTableWidgetItem(strscore.at(i)));
    }
}

Widget::~Widget()
{
    delete ui;
}

input Widgets 输入组控件

QComboBox

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QMessageBox>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setGeometry(300,200,1000,600);

    combobox = new QComboBox(this); // 实例化对象
    combobox->setGeometry(10,10,200,30);
    combobox->addItem("北京市");
    combobox->addItem("上海");
    combobox->addItem("广东");
    combobox->addItem("深圳");
    combobox->addItem("湖南");
    // 信号槽函数
    connect(combobox,SIGNAL(currentIndexChanged(int)),this,SLOT(comboboxIndex(int)));
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::comboboxIndex(int index){
    QMessageBox mybox(QMessageBox::Question,"信息",combobox->itemText(index),QMessageBox::Yes|QMessageBox::No);
    mybox.exec();
}

QFontComboBox

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QMessageBox>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setGeometry(300,200,1000,600);

    fontcombobox = new QFontComboBox(this);
    qlabel = new QLabel(this);
    fontcombobox->setGeometry(10,10,200,30);
    qlabel->setGeometry(10,30,300,50);
    connect(fontcombobox,SIGNAL(currentFontChanged(QFont)),this,SLOT(fontcomboboxFunc(QFont)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::fontcomboboxFunc(QFont font){
    qlabel->setFont(font);
    QString qStr = "凹凸曼";
    qlabel->setText(qStr);
}

Line Edit 单行输入框

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QMessageBox>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setGeometry(300,200,1000,600);
    this->setGeometry(300,200,1000,600);
    lineedit = new QLineEdit(this);
    lineedit->setGeometry(10,10,200,30);
    pushbutton = new QPushButton(this);
    pushbutton->setGeometry(220,10,100,30);
    pushbutton->setText("点击我");
    qlabely = new QLabel(this);
    qlabely->setGeometry(100,70,400,30);
    qlabely->setText("输入内容为");
    connect(pushbutton,SIGNAL(clicked()),this,SLOT(pushbuttonClicked()));
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::comboboxIndex(int index){
    QMessageBox mybox(QMessageBox::Question,"信息",combobox->itemText(index),QMessageBox::Yes|QMessageBox::No);
    mybox.exec();
}

void MainWindow::pushbuttonClicked(){
    QString qStr;
    qStr = "你输入内容为:";
    qStr = qStr+lineedit->text();
    qlabely->setText(qStr);
}

text Edit 多行文本编辑

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QMessageBox>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setGeometry(300,200,1000,600);

    plaintedit = new QPlainTextEdit(this);
    plaintedit->setGeometry(10,40,400,200);

    radiobutton = new QRadioButton(this);
    radiobutton->setGeometry(10,10,200,30);
    radiobutton->setText("只读模式");


    // 设置当前程序为工作目录
    QDir::setCurrent(QCoreApplication::applicationDirPath());
    QFile fe("moc_mainwindow.cpp");
    fe.open((QFile::ReadOnly | QFile::Text));
    QTextStream strin(&fe);
    plaintedit->insertPlainText(strin.readAll());
    connect(radiobutton,SIGNAL(clicked()),this,SLOT(radioButtonClicked()));
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::radioButtonClicked(){
    if(radiobutton->isChecked()){
        plaintedit->setReadOnly(true);
    }else{
        plaintedit->setReadOnly(false);
    }
}

Spin Box

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QMessageBox>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setGeometry(300,200,1000,600);

    plaintedit = new QPlainTextEdit(this);
    plaintedit->setGeometry(10,40,400,200);

    radiobutton = new QRadioButton(this);
    radiobutton->setGeometry(10,10,200,30);
    radiobutton->setText("只读模式");


    // 设置当前程序为工作目录
    QDir::setCurrent(QCoreApplication::applicationDirPath());
    QFile fe("moc_mainwindow.cpp");
    fe.open((QFile::ReadOnly | QFile::Text));
    QTextStream strin(&fe);
    plaintedit->insertPlainText(strin.readAll());
    connect(radiobutton,SIGNAL(clicked()),this,SLOT(radioButtonClicked()));


    // 改变窗口背景颜色
    this->setStyleSheet("QMainWindow{background-color:""rgba(255,250,100,100%)}");

    spinbox = new QSpinBox(this);
    spinbox->setGeometry(440,200,150,30);
    spinbox->setRange(0,100);
    spinbox->setSingleStep(10);

    spinbox->setSuffix("%不透明度");

    connect(spinbox,SIGNAL(valueChanged(int)),this,SLOT(spinboxValueChanged(int)));
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::radioButtonClicked(){
    if(radiobutton->isChecked()){
        plaintedit->setReadOnly(true);
    }else{
        plaintedit->setReadOnly(false);
    }
}

void MainWindow::spinboxValueChanged(int x){
    double dx = (double)x/100;
    this->setWindowOpacity(dx);
}

TimeEdit 时间编辑器

cpp 复制代码
    dte = new QDateTimeEdit(QDateTime::currentDateTime(),this);
    dte->setGeometry(440,290,220,30);

    te = new QTimeEdit(QTime::currentTime(),this);
    te->setGeometry(440,330,200,30);


    de = new QDateEdit(QDate::currentDate(),this);
    de->setGeometry(440,370,200,30);

Scroll Bar控件

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QMessageBox>
#include <QDebug>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setGeometry(300,200,1000,600);

    hscrollbar = new QScrollBar(Qt::Horizontal,this);
    hscrollbar->setGeometry(0,500,1000,30);
    vscrollbar = new QScrollBar(Qt::Vertical,this);
    vscrollbar->setGeometry(970,0,30,500);
}

MainWindow::~MainWindow()
{
    delete ui;
}

Key Sequence Edit 快捷键捕获

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QMessageBox>
#include <QDebug>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setGeometry(300,200,1000,600);
    kse = new QKeySequenceEdit(this);
    kse->setGeometry(0,0,200,30);
    connect(kse,SIGNAL(keySequenceChanged(const QKeySequence &)),this,SLOT(keysequeditChanged(const QKeySequence &)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::keysequeditChanged(const QKeySequence  &key){
    if(key==QKeySequence(tr("Ctrl+Q"))){
        this->close();
    }else{
        qDebug()<<key.toString();
    }
}

Display Widgets

label :标签

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QImageReader>

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {
  ui->setupUi(this);
  textlabelFunc();
}

Widget::~Widget() { delete ui; }

void Widget::textlabelFunc() {
  QString fName("D://0527.png");

  // 根据文件头自动识别真实格式(不依赖扩展名,即使 .jpg 实际是 PNG 也能识别)
  QByteArray format = QImageReader::imageFormat(fName);
  if (format.isEmpty()) {
    QMessageBox::information(this, "失败", "无法识别图片格式");
    return;
  }

  QImageReader reader(fName, format);
  QImage img = reader.read();
  if (img.isNull()) {
    QMessageBox::information(this, "失败", reader.errorString());
    return;
  }

  ui->labeljpg->setPixmap(QPixmap::fromImage(img));
}

Text Brower : 文本浏览器

cpp 复制代码
void Widget::textbrowserFuncReadTxt(){
    QString qStrdData;
    QFile qfile("d:\\01.txt");

    if(!(qfile.open(QIODevice::ReadOnly|QIODevice::Text))){
        QMessageBox::warning(this,"失败","打开文件失败,请重新检查");
    }

    while (!qfile.atEnd()) {
        QByteArray ay = qfile.readLine();
        QString strs(ay);
        qStrdData.append(strs);
    }

    ui->textBrowser->setText(qStrdData);
}

textBrowser 进度条

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QImageReader>

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {
  ui->setupUi(this);
  textlabelFunc();
  textbrowserFuncReadTxt();
}

Widget::~Widget() { delete ui; }

void Widget::textlabelFunc() {
  QString fName("D://0527.png");

  // 根据文件头自动识别真实格式(不依赖扩展名,即使 .jpg 实际是 PNG 也能识别)
  QByteArray format = QImageReader::imageFormat(fName);
  if (format.isEmpty()) {
    QMessageBox::information(this, "失败", "无法识别图片格式");
    return;
  }

  QImageReader reader(fName, format);
  QImage img = reader.read();
  if (img.isNull()) {
    QMessageBox::information(this, "失败", reader.errorString());
    return;
  }

  ui->labeljpg->setPixmap(QPixmap::fromImage(img));
  ui->labeljpg->setScaledContents(true);


  // 初始化进度条
  ui->progressBar->setRange(0,1000000);
  ui->progressBar->setValue(0);
}

void Widget::textbrowserFuncReadTxt(){
    QString qStrdData;
    QFile qfile("d:\\01.txt");

    if(!(qfile.open(QIODevice::ReadOnly|QIODevice::Text))){
        QMessageBox::warning(this,"失败","打开文件失败,请重新检查");
    }

    while (!qfile.atEnd()) {
        QByteArray ay = qfile.readLine();
        QString strs(ay);
        qStrdData.append(strs);
    }

    ui->textBrowser->setText(qStrdData);
}

void Widget::on_processButton_clicked()
{
    for(int i=1;i<=1000000;i++){
        for(int j=0;j<1;j++){
            ui->progressBar->setValue(i);
        }
    }
}

LCD Number 液晶数字

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QImageReader>

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {
  ui->setupUi(this);
  textlabelFunc();
  textbrowserFuncReadTxt();
}

Widget::~Widget() { delete ui; }

void Widget::textlabelFunc() {
  QString fName("D://0527.png");

  // 根据文件头自动识别真实格式(不依赖扩展名,即使 .jpg 实际是 PNG 也能识别)
  QByteArray format = QImageReader::imageFormat(fName);
  if (format.isEmpty()) {
    QMessageBox::information(this, "失败", "无法识别图片格式");
    return;
  }

  QImageReader reader(fName, format);
  QImage img = reader.read();
  if (img.isNull()) {
    QMessageBox::information(this, "失败", reader.errorString());
    return;
  }

  ui->labeljpg->setPixmap(QPixmap::fromImage(img));
  ui->labeljpg->setScaledContents(true);


  // 初始化进度条
  ui->progressBar->setRange(0,1000000);
  ui->progressBar->setValue(0);


  // 初始化
  initFunc();

  // 信号与槽函数连接
  connect(timers,&QTimer::timeout,this,&Widget::on_timerout);
}

void Widget::textbrowserFuncReadTxt(){
    QString qStrdData;
    QFile qfile("d:\\01.txt");

    if(!(qfile.open(QIODevice::ReadOnly|QIODevice::Text))){
        QMessageBox::warning(this,"失败","打开文件失败,请重新检查");
    }

    while (!qfile.atEnd()) {
        QByteArray ay = qfile.readLine();
        QString strs(ay);
        qStrdData.append(strs);
    }

    ui->textBrowser->setText(qStrdData);
}

void Widget::on_processButton_clicked()
{
    for(int i=1;i<=1000000;i++){
        for(int j=0;j<1;j++){
            ui->progressBar->setValue(i);
        }
    }
}
void Widget::on_timerout(){
    iValues++;
    ui->lcdNumber->display(iValues);
}
void Widget::on_startBtn_clicked()
{
    timers->start();
    ui->startBtn->setEnabled(false);
    ui->pauseBtn->setEnabled(true);
    ui->resetBtn->setEnabled(true);
}

void Widget::on_pauseBtn_clicked()
{
    timers->stop();
    ui->startBtn->setEnabled(true);
    ui->pauseBtn->setEnabled(false);
    ui->resetBtn->setEnabled(true);
}

void Widget::on_resetBtn_clicked()
{
    timers->stop();
    iValues = 0;
    ui->lcdNumber->display(iValues);
    ui->startBtn->setEnabled(true);
    ui->pauseBtn->setEnabled(true);
    ui->resetBtn->setEnabled(false);


}
void Widget::initFunc(){
    timers = new QTimer(this);
    timers->setInterval(1000);
    timers->stop();
}

doing后续补充~

相关推荐
爱喝水的鱼丶1 小时前
SAP-ABAP:SELECT大数据量查询性能调优——避免嵌套循环、减少数据库交互的核心方案
开发语言·数据库·sql·性能优化·sap·abap·erp
小黄蚁1 小时前
LVGL学习笔记(一)
笔记·学习
懿路向前2 小时前
【HarmonyOS学习笔记】2026-07-26 | @Trace 序列化 __ob_ 前缀陷阱与消息持久化
笔记·学习
一只小菜鸡..2 小时前
南京大学 操作系统 (JYY) 学习笔记:可执行文件、链接器与 Shebang 的彩蛋
笔记·学习
三8442 小时前
get方法/post方法/SQL注入文字型/数字型
数据库·sql·mysql
TDengine (老段)3 小时前
已有TSDB?一条配置,免费解锁AI数据管理平台
大数据·数据库·物联网·ai·时序数据库·tdengine·涛思数据
高铭杰3 小时前
Golang sync.Mutex实现原理学习
java·学习·golang
狗凯之家源码网3 小时前
狗凯源码库学习资源真实价值评测
学习