当前位置: 首页 > news >正文

Qt模型/视图编程详解:QStringListModel与多视图数据同步

本文将详细介绍Qt中的模型/视图编程框架,重点讲解QStringListModel的使用方法,以及如何实现多个视图之间的数据同步。

效果展示

在这里插入图片描述

项目概述

本应用主要实现以下功能:

  • 使用QListView和QTableView展示相同的数据
  • 使用QPlainTextEdit显示数据内容
  • 支持数据的添加、插入、删除和初始化操作
  • 实现多个视图之间的数据同步

模型/视图编程原理

1. 模型/视图架构概述

Qt的模型/视图架构将数据的存储(模型)和数据的显示(视图)分离开来,这种分离使得多个视图可以显示同一个模型的数据,并且可以独立地处理用户输入。

核心组件:

  • 模型(Model):负责管理数据,提供统一的接口供视图访问
  • 视图(View):负责显示模型中的数据,并处理用户交互
  • 委托(Delegate):负责渲染视图中的项目,并处理项目编辑

2. QStringListModel介绍

QStringListModel是Qt中一个简单的模型类,专门用于处理字符串列表数据。它继承自QAbstractListModel,提供了对字符串列表的基本操作接口。

主要特点:

  • 专门为字符串列表设计
  • 支持基本的增删改查操作
  • 可以同时用于列表视图和表格视图

实现步骤

1. 界面设计

首先在Qt Designer中创建主窗口,添加以下控件:

  • 三个GroupBox,分别包含ListView、TableView和PlainTextEdit
  • 五个PushButton:添加、插入、删除、加载到文本编辑框、清空列表、初始化
  • 工具栏和对应的Action:导入、保存、添加、插入、删除、预览、居左、居中、居右、粗体

2. 模型初始化和视图关联

在MainWindow的构造函数中初始化数据模型并与视图关联:

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 创建QStringListModel对象,用于管理字符串列表数据// QStringListModel是Qt提供的专门用于处理字符串列表的模型类model = new QStringListModel(this);// 准备初始数据,包含几个中国主要城市QStringList addList = {"北京", "上海", "广州", "深圳", "杭州", "长沙"};// 将数据设置到模型中// setStringList()方法会将整个字符串列表设置为模型的数据model->setStringList(addList);// 将同一个模型设置到ListView和TableView// 这样两个视图将显示相同的数据,并且保持同步ui->listView->setModel(model);ui->tableView->setModel(model);
}

代码解析:

  • QStringListModel是专门为字符串列表设计的模型类,提供了对字符串列表的基本操作接口
  • setStringList()方法将字符串列表设置为模型的数据源
  • 同一个模型可以设置到多个视图,实现数据的同步显示

3. 添加数据功能

实现在列表尾部添加新数据的功能:

void MainWindow::on_pushButtonAdd_clicked()
{// 在模型尾部插入一行空数据// insertRow()方法在指定位置插入新行,参数为行索引model->insertRow(model->rowCount());// 获取新插入行的索引// index()方法根据行号和列号创建模型索引QModelIndex index = model->index(model->rowCount() - 1, 0);// 设置新行的数据为"新的城市"// setData()方法设置指定索引的数据model->setData(index, "新的城市");// 在ListView中自动选中新添加的行// setCurrentIndex()方法设置当前选中的项ui->listView->setCurrentIndex(index);
}

代码解析:

  • insertRow()方法在指定位置插入新行,参数为行索引
  • index()方法根据行号和列号创建模型索引,用于定位模型中的特定项
  • setData()方法设置指定索引的数据
  • setCurrentIndex()方法设置视图中的当前选中项

4. 插入数据功能

实现在当前选中位置插入新数据的功能:

void MainWindow::on_pushButtonInsert_clicked()
{// 获取ListView中当前选中的项的索引// currentIndex()方法返回当前选中的模型索引QModelIndex index = ui->listView->currentIndex();// 在当前选中行之前插入新行model->insertRow(index.row());// 设置新插入行的数据model->setData(index, "新的城市");// 保持选中新插入的行ui->listView->setCurrentIndex(index);
}

代码解析:

  • currentIndex()方法获取当前选中的模型索引
  • insertRow()方法在指定位置插入新行
  • 插入新行后,保持选中状态以便用户继续操作

5. 删除数据功能

实现删除当前选中数据的功能:

void MainWindow::on_pushButtonDel_clicked()
{// 获取ListView中当前选中的项的索引QModelIndex index = ui->listView->currentIndex();// 删除当前选中的行// removeRow()方法删除指定行,参数为行索引model->removeRow(index.row());
}

代码解析:

  • removeRow()方法删除指定行,参数为行索引
  • 删除操作会同时更新所有使用该模型的视图

6. 加载数据到文本编辑框

实现将模型中的数据加载到文本编辑框的功能:

void MainWindow::on_pushButtonLoadData2TextEdit_clicked()
{// 从模型中获取完整的字符串列表// stringList()方法返回模型中的所有字符串QStringList list = model->stringList();// 清空文本编辑框ui->plainTextEdit->clear();// 遍历字符串列表,将每个字符串添加到文本编辑框for(int i = 0; i < list.count(); i++) {// append()方法在文本编辑框末尾添加文本ui->plainTextEdit->append(list[i]);}
}

代码解析:

  • stringList()方法返回模型中的所有字符串
  • clear()方法清空文本编辑框的内容
  • append()方法在文本编辑框末尾添加文本

7. 清空列表功能

实现清空模型中所有数据的功能:

void MainWindow::on_pushButtonClearList_clicked()
{// 删除模型中所有行// removeRows()方法删除从指定位置开始的指定数量的行// 参数1:起始行索引,参数2:要删除的行数model->removeRows(0, model->rowCount());
}

代码解析:

  • removeRows()方法删除从指定位置开始的指定数量的行
  • 参数1是起始行索引,参数2是要删除的行数
  • rowCount()方法返回模型中的总行数

8. 初始化数据功能

实现将模型数据重置为初始状态的功能:

void MainWindow::on_pushButtonInit_clicked()
{// 准备初始数据QStringList addList = {"北京", "上海", "广州", "深圳", "杭州"};// 将初始数据设置到模型中model->setStringList(addList);
}

代码解析:

  • setStringList()方法将整个字符串列表设置为模型的数据
  • 这会替换模型中现有的所有数据

完整代码

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QTextEdit> // 文本编辑框头文件
#include <QStringListModel> // 字符串列表模型头文件QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:// 构造函数MainWindow(QWidget *parent = nullptr);// 析构函数~MainWindow();private slots:// 添加按钮点击槽函数void on_pushButtonAdd_clicked();// 插入按钮点击槽函数void on_pushButtonInsert_clicked();// 删除按钮点击槽函数void on_pushButtonDel_clicked();// 加载数据到文本编辑框按钮点击槽函数void on_pushButtonLoadData2TextEdit_clicked();// 清空列表按钮点击槽函数void on_pushButtonClearList_clicked();// 初始化按钮点击槽函数void on_pushButtonInit_clicked();private:Ui::MainWindow *ui; // UI指针QStringListModel *model; // 字符串列表模型指针
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 创建QStringListModel对象,用于管理字符串列表数据model = new QStringListModel(this);// 准备初始数据,包含几个中国主要城市QStringList addList = {"北京", "上海", "广州", "深圳", "杭州", "长沙"};// 将数据设置到模型中model->setStringList(addList);// 将同一个模型设置到ListView和TableView// 这样两个视图将显示相同的数据,并且保持同步ui->listView->setModel(model);ui->tableView->setModel(model);
}MainWindow::~MainWindow()
{delete ui; // 释放UI资源
}// 添加按钮点击槽函数实现
void MainWindow::on_pushButtonAdd_clicked()
{// 在模型尾部插入一行空数据model->insertRow(model->rowCount());// 获取新插入行的索引QModelIndex index = model->index(model->rowCount() - 1, 0);// 设置新行的数据为"新的城市"model->setData(index, "新的城市");// 在ListView中自动选中新添加的行ui->listView->setCurrentIndex(index);
}// 插入按钮点击槽函数实现
void MainWindow::on_pushButtonInsert_clicked()
{// 获取ListView中当前选中的项的索引QModelIndex index = ui->listView->currentIndex();// 在当前选中行之前插入新行model->insertRow(index.row());// 设置新插入行的数据model->setData(index, "新的城市");// 保持选中新插入的行ui->listView->setCurrentIndex(index);
}// 删除按钮点击槽函数实现
void MainWindow::on_pushButtonDel_clicked()
{// 获取ListView中当前选中的项的索引QModelIndex index = ui->listView->currentIndex();// 删除当前选中的行model->removeRow(index.row());
}// 加载数据到文本编辑框按钮点击槽函数实现
void MainWindow::on_pushButtonLoadData2TextEdit_clicked()
{// 从模型中获取完整的字符串列表QStringList list = model->stringList();// 清空文本编辑框ui->plainTextEdit->clear();// 遍历字符串列表,将每个字符串添加到文本编辑框for(int i = 0; i < list.count(); i++) {ui->plainTextEdit->append(list[i]);}
}// 清空列表按钮点击槽函数实现
void MainWindow::on_pushButtonClearList_clicked()
{// 删除模型中所有行model->removeRows(0, model->rowCount());
}// 初始化按钮点击槽函数实现
void MainWindow::on_pushButtonInit_clicked()
{// 准备初始数据QStringList addList = {"北京", "上海", "广州", "深圳", "杭州"};// 将初始数据设置到模型中model->setStringList(addList);
}

文件系统模型使用详解

除了QStringListModel,Qt还提供了QFileSystemModel用于文件系统操作。虽然本示例中没有使用,但了解它的基本用法对模型/视图编程很有帮助。

QFileSystemModel基本用法

// 创建文件系统模型
QFileSystemModel *fileModel = new QFileSystemModel(this);// 设置根路径
fileModel->setRootPath(QDir::currentPath());// 将模型设置到视图
ui->treeView->setModel(fileModel);
ui->treeView->setRootIndex(fileModel->index(QDir::currentPath()));

主要特点:

  • 专门用于表示本地文件系统
  • 自动监视文件系统的变化并更新模型
  • 提供文件图标、大小、修改日期等信息

字符串链表模型使用详解

QStringListModel是QAbstractListModel的子类,专门用于处理字符串列表。它提供了对字符串列表的基本操作接口,可以同时用于列表视图和表格视图。

QStringListModel常用方法

  1. setStringList() - 设置模型的字符串列表
  2. stringList() - 获取模型的字符串列表
  3. insertRow() - 在指定位置插入新行
  4. removeRow() - 删除指定行
  5. setData() - 设置指定索引的数据
  6. data() - 获取指定索引的数据

总结

本文详细介绍了Qt中的模型/视图编程框架,重点讲解了QStringListModel的使用方法。通过这个示例,我们学习了:

  1. 模型/视图架构原理:数据与显示的分离,实现多个视图同步
  2. QStringListModel的基本使用方法:创建模型、设置数据、与视图关联
  3. 数据操作功能实现:添加、插入、删除、清空和初始化数据
  4. 多视图数据同步:同一个模型设置到多个视图,实现数据同步更新

文章转载自:

http://dCmfpQwD.tpxry.cn
http://g1Z7zeNP.tpxry.cn
http://5K9y0zO1.tpxry.cn
http://7f0DhnLC.tpxry.cn
http://AMFV4b1S.tpxry.cn
http://fK6WN587.tpxry.cn
http://9w9gSv8E.tpxry.cn
http://Ggf4jwbX.tpxry.cn
http://5vaGCQSs.tpxry.cn
http://b8YbfGjv.tpxry.cn
http://35F6BdRw.tpxry.cn
http://Ff3sWnjf.tpxry.cn
http://UckG3zpB.tpxry.cn
http://yIW4RBux.tpxry.cn
http://F9HE8SNP.tpxry.cn
http://Sd6peCWT.tpxry.cn
http://hOIbe4WD.tpxry.cn
http://urh9pyMH.tpxry.cn
http://fdpTiZcs.tpxry.cn
http://xU2eR8F8.tpxry.cn
http://rwP0GkZi.tpxry.cn
http://TqZbdM7M.tpxry.cn
http://SrlC6ZrE.tpxry.cn
http://0sabhkrV.tpxry.cn
http://sgOA9NkR.tpxry.cn
http://aGGnfvPh.tpxry.cn
http://16lJjcmY.tpxry.cn
http://4r4VzqfJ.tpxry.cn
http://qHCRfglK.tpxry.cn
http://NLwfQQ7C.tpxry.cn
http://www.dtcms.com/a/363314.html

相关文章:

  • 链表题类型注解解惑:理解Optional,理解ListNode
  • 前端实现解析【导入】数据后调用批量处理接口
  • GaussDB 等待事件为LockMgrLock处理方法
  • 为什么程序员总是发现不了自己的Bug?
  • flutter踩坑插件:Swift架构不兼容
  • 疯狂星期四文案网第58天运营日记
  • 手撕Redis底层2-网络模型深度剖析
  • 【3D 入门-4】trimesh 极速上手之 3D Mesh 数据结构解析(Vertices / Faces)
  • Valkey vs Redis详解
  • 基于若依框架开发WebSocket接口
  • 计算机Python毕业设计推荐:基于Django+Vue用户评论挖掘旅游系统
  • 【交易系统系列36】揭秘币安(Binance)技术心脏:从公开信息拼凑“MatchBox”撮合引擎架构
  • 海康摄像头开发---标准配置结构体(NET_DVR_STD_CONFIG)
  • End-To-End 之于推荐-kuaishou OneRec2 笔记
  • css中 ,有哪些⽅式可以隐藏页⾯元素? 区别?
  • 03_网关ip和端口映射(路由器转发)操作和原理
  • Telnet 原理与配置
  • 基于STM32单片机智能家居wifi远程监控系统机智云app设计
  • Replit在线编程工具:支持多语言环境免配置与实时协作,助力编程学习调试与社区项目复用
  • Spring Security的@PreAuthorize注解为什么会知道用户角色?
  • 0902 C++类的匿名对象
  • Nano Banana 复刻分镜,多图结合片刻生成想要的视频
  • 适配第一性原理与分子动力学研究的高性能工作站解析
  • 信息安全各类加密算法解析
  • LDR6600:2C1A适配器协议方案芯片
  • 综合诊断板CAN时间戳稳定性测试报告8.28
  • Nek La Vita È DJ大来 安装教程 简单步骤 教你怎么装(附安装包下载)
  • Windows 命令行:父目录与子目录
  • 力扣222 代码随想录Day15 第四题
  • 缓存工具服务(封装缓存击穿+缓存穿透+缓存雪崩)