解码Qt 视图窗口与多界面组件

Qt 视图窗口核心分类

Qt 视图窗口分为 Item-Based(基于项)和 Model-Based(基于模型)两类,核心区别如下:

类型核心特点典型控件
Item-Based直接操作控件的「项」(Item)实现数据更新,数据与视图耦合度高QListWidget、QTableWidget、QTreeWidget
Model-Based数据存储在「模型」中,视图仅负责展示,数据与视图解耦,支持实时更新、数据共享QListView、QTableView、QTreeView

基础模型类说明(Model-Based 核心)

所有模型类均继承自 QAbstractItemModel,以下是常用模型的核心作用:

  • QAbstractListModel:抽象列表模型,定义列表数据的基础接口(需子类化实现具体逻辑)。
  • QAbstractTableModel:抽象表格模型,定义表格数据的基础接口(需子类化实现具体逻辑)。
  • QAbstractProxyModel:抽象代理模型,用于对已有模型做数据转换(如排序、过滤、合并)。
  • QConcatenateTablesProxyModel:代理模型,将多个表格模型按行拼接为一个模型。
  • QDirModel:已废弃(Qt5+ 推荐 QFileSystemModel),用于访问文件系统目录结构。
  • QFileSystemModel:文件系统模型,实时获取本地文件/目录信息(支持动态更新)。
  • QStandardItemModel:通用标准模型,无需子类化即可快速实现列表/表格/树形数据存储(简化 Model-Based 开发)。

Item-Based 核心控件

QListWidget(列表控件)

image

核心概念

以列表形式展示项(文本、图标、自定义控件),直接操作 QListWidgetItem 实现数据管理,适用于简单列表场景。

基础操作:添加内容

添加纯文本项

/**
 * 添加单个文本项到列表末尾
 * @brief addItem
 * @param label 要显示的文本内容
 * @return void 无返回值
 */
ui->listWidget->addItem("Hello Widget");

/**
 * 批量添加文本项到列表末尾
 * @brief addItems
 * @param labels 文本列表(QStringList)
 * @return void 无返回值
 */
QStringList strList;
strList << "123" << "456" << "789" << "000";
ui->listWidget->addItems(strList);

image

添加带图标的项

/**
 * 构造带图标和文本的列表项
 * @brief QListWidgetItem 构造函数
 * @param icon 项的图标(QIcon),支持本地图片路径/资源文件
 * @param text 项的文本内容
 * @param parent 所属的QListWidget(可选)
 * @return QListWidgetItem* 构造的项对象(需手动管理内存)
 */
QListWidgetItem *item = new QListWidgetItem(QIcon("./img/123.jpg"), "Hello Icon");
/**
 * 添加自定义项到列表末尾
 * @brief addItem
 * @param item 已构造的QListWidgetItem对象
 * @return void 无返回值
 */
ui->listWidget->addItem(item);

image

添加自定义控件/窗口

image

// 1. 构造自定义窗口(如自定义的Friend窗口)
Friend *newFriend = new Friend();

// 2. 构造空白列表项(仅作为载体)
QListWidgetItem *newItem = new QListWidgetItem();
ui->listWidget->addItem(newItem);

/**
 * 设置列表项的尺寸(匹配自定义窗口大小)
 * @brief setSizeHint
 * @param size 目标尺寸(QSize),一般取自定义窗口的推荐尺寸
 * @return void 无返回值
 */
newItem->setSizeHint(newFriend->sizeHint());

/**
 * 给列表项绑定自定义控件
 * @brief setItemWidget
 * @param item 目标列表项
 * @param widget 要显示的自定义控件/窗口
 * @return void 无返回值
 */
ui->listWidget->setItemWidget(newItem, newFriend);

信号与槽(核心交互)

信号触发场景参数说明
currentRowChanged(int)当前选中行发生变化时currentRow:新选中行的索引(从0开始)
currentTextChanged(QString)当前选中项的文本发生变化时currentText:新选中项的文本内容
itemClicked(QListWidgetItem*)单击某一项时item:被单击的项对象
itemDoubleClicked(QListWidgetItem*)双击某一项时item:被双击的项对象
itemSelectionChanged()选中项发生变化时(无参数)-

示例1:获取选中行/文本

image

/**
 * 选中行变化时触发的槽函数
 * @brief on_listWidget_currentRowChanged
 * @param currentRow 新选中行的索引(-1表示无选中)
 * @return void 无返回值
 */
void MainWindow::on_listWidget_currentRowChanged(int currentRow)
{
    qDebug() << "当前选中行:" << currentRow;
}

image

/**
 * 选中项文本变化时触发的槽函数
 * @brief on_listWidget_currentTextChanged
 * @param currentText 新选中项的文本
 * @return void 无返回值
 */
void MainWindow::on_listWidget_currentTextChanged(const QString &currentText)
{
    qDebug() << "当前选中文本:" << currentText;
    ui->groupBox->setTitle(currentText); // 同步更新分组框标题
}

image

示例2:双击删除项

/**
 * 双击项时删除该项目
 * @brief on_listWidget_itemDoubleClicked
 * @param item 被双击的项对象
 * @return void 无返回值
 * @note removeItemWidget仅移除项内的控件,不删除项;takeItem删除项并返回对象(需手动释放内存)
 */
void MainWindow::on_listWidget_itemDoubleClicked(QListWidgetItem *item)
{
    int row = ui->listWidget->row(item); // 获取项的行索引
    /**
     * 删除指定行的项
     * @brief takeItem
     * @param row 要删除的行索引
     * @return QListWidgetItem* 被删除的项对象(需手动delete释放,否则内存泄漏)
     */
    QListWidgetItem *delItem = ui->listWidget->takeItem(row);
    delete delItem; // 释放内存
}

image

常用接口(QListWidget/QListWidgetItem)

QListWidget 核心接口

/**
 * 在指定行插入文本项
 * @brief insertItem
 * @param row 插入位置(索引)
 * @param text 文本内容
 * @return void 无返回值
 */
ui->listWidget->insertItem(1, "插入到第2行的项");

/**
 * 获取指定行的项对象
 * @brief item
 * @param row 目标行索引
 * @return QListWidgetItem* 目标行的项(NULL表示行不存在)
 */
QListWidgetItem *targetItem = ui->listWidget->item(0);

/**
 * 获取当前选中项
 * @brief currentItem
 * @return QListWidgetItem* 当前选中项(NULL表示无选中)
 */
QListWidgetItem *curItem = ui->listWidget->currentItem();

QListWidgetItem 核心接口

/**
 * 设置项的文本颜色
 * @brief setTextColor
 * @param color 目标颜色(QColor)
 * @return void 无返回值
 */
item->setTextColor(Qt::red);

/**
 * 设置项的复选框状态
 * @brief setCheckState
 * @param state 复选状态(Qt::Unchecked/Checked/PartiallyChecked)
 * @return void 无返回值
 */
item->setCheckState(Qt::Checked);

/**
 * 设置项的提示文本(鼠标悬浮时显示)
 * @brief setToolTip
 * @param tip 提示文本
 * @return void 无返回值
 */
item->setToolTip("这是一个带图标的项");

QTableWidget(表格控件)

核心概念

基于项的表格控件,直接操作 QTableWidgetItem 管理单元格数据,支持嵌入自定义控件,适用于简单表格场景。

基础操作:添加内容

初始化表格行列

/**
 * 设置表格行数
 * @brief setRowCount
 * @param rows 行数(正整数)
 * @return void 无返回值
 */
ui->tableWidget->setRowCount(5);

/**
 * 设置表格列数
 * @brief setColumnCount
 * @param columns 列数(正整数)
 * @return void 无返回值
 */
ui->tableWidget->setColumnCount(3);

/**
 * 设置水平表头标签
 * @brief setHorizontalHeaderLabels
 * @param labels 表头文本列表(QStringList)
 * @return void 无返回值
 */
QStringList headerLabels;
headerLabels << "姓名" << "年龄" << "性别";
ui->tableWidget->setHorizontalHeaderLabels(headerLabels);

添加文本单元格

/**
 * 构造表格单元格项
 * @brief QTableWidgetItem 构造函数
 * @param text 单元格文本
 * @return QTableWidgetItem* 单元格项对象
 */
QTableWidgetItem *newItem = new QTableWidgetItem("张三");

/**
 * 设置指定单元格的项
 * @brief setItem
 * @param row 行索引(从0开始)
 * @param column 列索引(从0开始)
 * @param item 单元格项对象
 * @return void 无返回值
 */
ui->tableWidget->setItem(0, 0, newItem);

添加自定义控件(如按钮)

/**
 * 构造自定义按钮
 * @brief QPushButton 构造函数
 * @param text 按钮文本
 * @param parent 父控件(可选)
 * @return QPushButton* 按钮对象
 */
QPushButton *btn = new QPushButton("点击", this);
connect(btn, &QPushButton::clicked, []() {
    qDebug() << "表格内按钮被点击";
});

/**
 * 设置指定单元格的自定义控件
 * @brief setCellWidget
 * @param row 行索引
 * @param column 列索引
 * @param widget 要嵌入的控件对象
 * @return void 无返回值
 */
ui->tableWidget->setCellWidget(0, 2, btn);

image

表格布局优化

/**
 * 设置表头拉伸模式(最后一列填充剩余空间)
 * @brief setStretchLastSection
 * @param stretch 是否拉伸(true/false)
 * @return void 无返回值
 */
ui->tableWidget->horizontalHeader()->setStretchLastSection(true);

/**
 * 设置所有列平均拉伸
 * @brief setSectionResizeMode
 * @param mode 拉伸模式(QHeaderView::Stretch 表示平均拉伸)
 * @return void 无返回值
 */
ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);

核心信号

信号触发场景参数说明
cellClicked(int, int)单击单元格时row:行索引,column:列索引
cellDoubleClicked(int, int)双击单元格时row:行索引,column:列索引
currentCellChanged(int, int, int, int)当前选中单元格变化时当前行、当前列、之前行、之前列

QTreeWidget(树形控件)

核心概念

基于项的树形控件,通过 QTreeWidgetItem 构建层级结构,支持多列树形展示,适用于简单树形数据场景。

基础操作:构建树形结构

/**
 * 设置树形控件列数
 * @brief setColumnCount
 * @param columns 列数(默认1列)
 * @return void 无返回值
 */
ui->treeWidget->setColumnCount(1);
ui->treeWidget->setHeaderLabel("树形结构示例");

/**
 * 构造根节点
 * @brief QTreeWidgetItem 构造函数
 * @param parent 父节点(NULL表示根节点,也可传treeWidget)
 * @return QTreeWidgetItem* 节点对象
 */
QTreeWidgetItem *rootItem = new QTreeWidgetItem(ui->treeWidget);
rootItem->setText(0, "根节点"); // 设置第0列文本

/**
 * 构造子节点(父节点为rootItem)
 * @brief QTreeWidgetItem 构造函数
 * @param parent 父节点对象
 * @return QTreeWidgetItem* 子节点对象
 */
QTreeWidgetItem *childItem1 = new QTreeWidgetItem(rootItem);
childItem1->setText(0, "一级子节点");

/**
 * 构造孙子节点(父节点为childItem1)
 */
QTreeWidgetItem *childItem2 = new QTreeWidgetItem(childItem1);
childItem2->setText(0, "二级子节点");

/*公共槽函数*/
rootItem->expand(); // 展开根节点

image

常用接口

/**
 * 设置是否显示根节点的展开/折叠图标
 * @brief setRootIsDecorated
 * @param decorate 是否显示(true显示,false隐藏)
 * @return void 无返回值
 */
ui->treeWidget->setRootIsDecorated(false);

/**
 * 设置是否启用排序
 * @brief setSortingEnabled
 * @param enable 是否启用(true启用,false禁用)
 * @return void 无返回值
 */
ui->treeWidget->setSortingEnabled(true);

Model-Based 核心控件:QTreeView

核心概念

基于模型的树形视图,必须配合模型使用(数据存储在模型,视图仅展示),支持实时更新、数据共享,适用于复杂/动态树形数据场景(如文件系统)。

核心接口

/**
 * 设置视图的数据源模型
 * @brief setModel
 * @param model 继承自QAbstractItemModel的模型对象
 * @return void 无返回值
 */
void setModel(QAbstractItemModel *model);

/**
 * 展开指定索引的节点
 * @brief expand
 * @param index 模型中的索引(QModelIndex)
 * @return void 无返回值
 */
void expand(const QModelIndex &index);

/**
 * 设置视图的根索引(仅展示模型中该索引下的子数据)
 * @brief setRootIndex
 * @param index 模型中的根索引
 * @return void 无返回值
 */
void setRootIndex(const QModelIndex &index);

示例:展示文件系统

image

/**
 * 构造文件系统模型
 * @brief QFileSystemModel 构造函数
 * @param parent 父对象(可选)
 * @return QFileSystemModel* 模型对象
 */
QFileSystemModel *fileModel = new QFileSystemModel(this);

/**
 * 设置模型监控的根路径
 * @brief setRootPath
 * @param path 本地路径(如"D:/")
 * @return QString 标准化后的路径
 */
fileModel->setRootPath("D:/");

// 给QTreeView设置模型
ui->treeView->setModel(fileModel);

/**
 * 获取指定路径在模型中的索引
 * @brief index
 * @param path 目标路径
 * @return QModelIndex 路径对应的模型索引
 */
QModelIndex targetIndex = fileModel->index("D:/APP");

// 设置视图仅展示"D:/APP"下的文件/目录
ui->treeView->setRootIndex(targetIndex);

// 隐藏不需要的列(QFileSystemModel默认列:名称、大小、类型、修改时间)
ui->treeView->hideColumn(1);
ui->treeView->hideColumn(2);
ui->treeView->hideColumn(3);

image

Qt 多界面组件

MDI 窗口(Multiple Document Interface多文档界面)

核心概念

在一个主窗口内显示多个子窗口,子窗口可层叠/平铺,适用于同时编辑多个文档的场景(如多文本编辑器)。核心类:

  • QMdiArea:容纳子窗口的容器(需设置为QMainWindow的中央控件)。
  • QMdiSubWindow:MDI子窗口(可嵌入任意QWidget作为内容)。

示例代码

#include <QApplication>
#include <QMdiArea>
#include <QMdiSubWindow>
#include <QTextEdit>
#include <QMainWindow>

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

    // 1. 构造MDI容器
    /**
     * 构造MDI容器
     * @brief QMdiArea 构造函数
     * @param parent 父对象(可选)
     * @return QMdiArea* MDI容器对象
     */
    QMdiArea *mdiArea = new QMdiArea;

    // 2. 构造第一个子窗口
    QMdiSubWindow *subWin1 = new QMdiSubWindow;
    QTextEdit *edit1 = new QTextEdit;
    /**
     * 设置子窗口的内容控件
     * @brief setWidget
     * @param widget 要嵌入的内容控件
     * @return void 无返回值
     */
    subWin1->setWidget(edit1);
    subWin1->setWindowTitle("文档1"); // 设置子窗口标题

    // 3. 构造第二个子窗口
    QMdiSubWindow *subWin2 = new QMdiSubWindow;
    QTextEdit *edit2 = new QTextEdit;
    subWin2->setWidget(edit2);
    subWin2->setWindowTitle("文档2");

    // 4. 添加子窗口到MDI容器
    /**
     * 添加子窗口到MDI容器
     * @brief addSubWindow
     * @param subWindow MDI子窗口对象
     * @return QMdiSubWindow* 添加后的子窗口对象(与入参一致)
     */
    mdiArea->addSubWindow(subWin1);
    mdiArea->addSubWindow(subWin2);

    // 5. 设置主窗口
    QMainWindow mainWin;
    mainWin.setCentralWidget(mdiArea); // MDI容器作为中央控件
    mainWin.setWindowTitle("MDI多文档示例");
    mainWin.resize(800, 600);

    // 6. 子窗口布局(平铺)
    /**
     * 平铺所有子窗口
     * @brief tileSubWindows
     * @return void 无返回值
     */
    mdiArea->tileSubWindows();

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

image

常用接口

/**
 * 层叠排列所有子窗口
 * @brief cascadeSubWindows
 * @return void 无返回值
 */
mdiArea->cascadeSubWindows();

/**
 * 设置活动子窗口
 * @brief setActiveSubWindow
 * @param subWindow 目标子窗口(NULL表示取消激活)
 * @return void 无返回值
 */
mdiArea->setActiveSubWindow(subWin1);

Dock 窗口(停靠窗口)

核心概念

可浮动、可停靠在主窗口边缘的窗口,适用于工具栏、属性面板等场景。核心类:

  • QDockWidget:停靠窗口容器(需嵌入QMainWindow)。
  • QMainWindow:提供停靠区域(左/右/上/下)。

示例代码

#include <QApplication>
#include <QMainWindow>
#include <QDockWidget>
#include <QPushButton>

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

    // 1. 构造主窗口
    QMainWindow mainWin;
    mainWin.setWindowTitle("Dock停靠窗口示例");
    mainWin.resize(800, 600);

    // 2. 构造Dock窗口
    /**
     * 构造停靠窗口
     * @brief QDockWidget 构造函数
     * @param title 停靠窗口标题
     * @param parent 父对象(可选)
     * @return QDockWidget* 停靠窗口对象
     */
    QDockWidget *dockWidget = new QDockWidget("工具栏", &mainWin);

    // 3. 构造Dock内容(按钮)
    QPushButton *btn = new QPushButton("停靠窗口按钮", dockWidget);
    dockWidget->setWidget(btn); // 设置Dock内容

    // 4. 设置Dock允许的停靠区域
    /**
     * 设置允许的停靠区域
     * @brief setAllowedAreas
     * @param areas 停靠区域(Qt::LeftDockWidgetArea/Right/Top/Bottom/AllDockWidgetAreas)
     * @return void 无返回值
     */
    dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);

    // 5. 将Dock添加到主窗口左侧
    /**
     * 添加Dock窗口到主窗口
     * @brief addDockWidget
     * @param area 初始停靠区域
     * @param dockwidget 停靠窗口对象
     * @return void 无返回值
     */
    mainWin.addDockWidget(Qt::LeftDockWidgetArea, dockWidget);

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

image

QTabWidget(标签窗口)

核心概念

在一个窗口内通过标签切换多个页面,适用于分类展示不同内容(如多标签浏览器、配置面板)。

示例代码

#include <QApplication>
#include <QTabWidget>
#include <QTextEdit>
#include <QIcon>

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

    // 1. 构造标签窗口
    QTabWidget *tabWidget = new QTabWidget;
    tabWidget->setWindowTitle("标签窗口示例");
    tabWidget->resize(600, 400);

    // 2. 添加标签页1(文本编辑器)
    /**
     * 添加标签页
     * @brief addTab
     * @param page 标签页内容控件
     * @param label 标签文本
     * @return int 标签页索引(从0开始)
     */
    QTextEdit *edit1 = new QTextEdit;
    int tab1Index = tabWidget->addTab(edit1, "标签1");
    /**
     * 设置标签页图标
     * @brief setTabIcon
     * @param index 标签页索引
     * @param icon 图标(QIcon)
     * @return void 无返回值
     */
    tabWidget->setTabIcon(tab1Index, QIcon(":/images/tab1.png"));

    // 3. 添加标签页2
    QTextEdit *edit2 = new QTextEdit;
    tabWidget->addTab(edit2, "标签2");

    // 4. 添加标签页3(禁用)
    QTextEdit *edit3 = new QTextEdit;
    int tab3Index = tabWidget->addTab(edit3, "标签3");
    /**
     * 设置标签页是否可用
     * @brief setTabEnabled
     * @param index 标签页索引
     * @param enabled 是否可用(true可用,false禁用)
     * @return void 无返回值
     */
    tabWidget->setTabEnabled(tab3Index, false);

    // 5. 设置当前选中标签页
    /**
     * 设置当前选中标签页
     * @brief setCurrentIndex
     * @param index 标签页索引
     * @return void 无返回值
     */
    tabWidget->setCurrentIndex(1); // 选中第二个标签页

    // 6. 开启标签页可关闭(显示×按钮)
    /**
     * 设置标签页是否可关闭
     * @brief setTabsClosable
     * @param closable 是否可关闭(true显示关闭按钮)
     * @return void 无返回值
     */
    tabWidget->setTabsClosable(true);

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

image

常用接口

/**
 * 移除指定标签页
 * @brief removeTab
 * @param index 标签页索引
 * @return void 无返回值
 * @note 仅移除标签页,内容控件需手动释放内存
 */
tabWidget->removeTab(0);

/**
 * 获取标签页数量
 * @brief count
 * @return int 标签页数量(正整数)
 */
int tabCount = tabWidget->count();

/**
 * 设置标签页可拖动
 * @brief setMovable
 * @param movable 是否可拖动(true允许拖动调整顺序)
 * @return void 无返回值
 */
tabWidget->setMovable(true);

关键注意事项

  • 内存管理:Item-Based 控件中,takeItem/takeRow 仅移除项,需手动 delete 释放对象;Model-Based 控件中,模型负责数据内存管理,视图仅展示。
  • 性能优化:大量数据场景优先使用 Model-Based 控件(如 QTableView 替代 QTableWidget),避免 Item-Based 控件的性能瓶颈。
  • 自定义控件嵌入:QListWidget/QTableWidget 嵌入自定义控件时,需通过 setSizeHint 匹配项/单元格尺寸,否则控件可能显示不全。
  • 信号与槽参数:QListWidget/QTableWidget 的信号参数(如 currentRowChanged)中,索引从 0 开始,-1 表示无选中项。
源码地址: https://pan.quark.cn/s/d1f41682e390 miyoubiAuto 米游社每日米游币自动化Python脚本(务必使用Python3) 8更新:更换cookie的获取地址 注意:禁止在B站、贴吧、或各大论坛大肆传播! 作者已退游,项目不维护了。 如果有能力的可以pr修复。 小引一波 推荐关注几个非常可爱有趣的女孩! 欢迎B站搜索: @嘉然今天吃什么 @向晚大魔王 @乃琳Queen @贝拉kira 第三方库 食用方法 下载源码 在Global.py中设置米游社Cookie 运行myb.py 本地第一次运行时会自动生产一个文件储存cookie,请勿删除 当前仅支持单个账号! 获取Cookie方法 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 按刷新页面,按下图复制 Cookie: How to get mys cookie 当触发时,可尝试按关闭,然后再次刷新页面,最后复制 Cookie。 也可以使用另一种方法: 复制代码 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 控制台粘贴代码并运行,获得类似的输出信息 部分即为所需复制的 Cookie,点击确定复制 部署方法--腾讯云函数版(推荐! ) 下载项目源码和压缩包 进入项目文件夹打开命令行执行以下命令 xxxxxxx为通过上面方式或取得米游社cookie 一定要用双引号包裹!! 例如: png 复制返回内容(包括括号) 例如: QQ截图20210505031552.png 登录腾讯云函数官网 选择函数服务-新建-自定义创建 函数名称随意-地区随意-运行环境Python3....
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值