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常用方法
- setStringList() - 设置模型的字符串列表
- stringList() - 获取模型的字符串列表
- insertRow() - 在指定位置插入新行
- removeRow() - 删除指定行
- setData() - 设置指定索引的数据
- data() - 获取指定索引的数据
总结
本文详细介绍了Qt中的模型/视图编程框架,重点讲解了QStringListModel的使用方法。通过这个示例,我们学习了:
- 模型/视图架构原理:数据与显示的分离,实现多个视图同步
- QStringListModel的基本使用方法:创建模型、设置数据、与视图关联
- 数据操作功能实现:添加、插入、删除、清空和初始化数据
- 多视图数据同步:同一个模型设置到多个视图,实现数据同步更新