本文将详细介绍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_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
// 构造函数
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的基本使用方法:创建模型、设置数据、与视图关联
- 数据操作功能实现:添加、插入、删除、清空和初始化数据
- 多视图数据同步:同一个模型设置到多个视图,实现数据同步更新