Qt表格数据处理应用开发详解:QStandardItemModel与QTableView使用指南
·
概述
本文将详细介绍如何使用Qt开发一个功能完整的表格数据处理应用。我们将重点讲解QStandardItemModel和QTableView的使用方法,并通过实际案例展示如何实现数据的导入、编辑、保存以及格式设置等功能。

应用功能概览
本应用主要实现以下功能:
- 文本数据文件的导入和保存
- 表格数据的添加、插入和删除
- 数据预览功能
- 单元格格式设置(居左、居中、居右、粗体)
- 状态栏实时显示当前单元格信息
界面设计
应用界面主要包含以下控件:
- 一个TableView用于显示和编辑表格数据
- 一个PlainTextEdit用于预览数据
- 两个GroupBox分别容纳上述控件
- 工具栏包含多个功能按钮
核心控件详解
1. QStandardItemModel标准项模型
QStandardItemModel是Qt中一个强大的数据模型类,它提供了项(item)的标准模型,可以用于存储自定义数据。与QTableView结合使用,可以创建功能丰富的表格应用程序。
关键特性:
- 支持行列操作
- 支持项的选择和编辑
- 可以存储任意数据
- 支持复选框等控件
初始化代码:
// 在MainWindow构造函数中初始化模型
colCount = 6; // 设置表格列数
model = new QStandardItemModel(2, colCount, this); // 创建模型,初始2行6列
2. QTableView使用详解
QTableView是Qt中用于显示和编辑表格数据的视图组件,它需要与数据模型(如QStandardItemModel)配合使用。
关键配置:
// 设置表格视图的选择模式和选择行为
ui->tableView->setSelectionMode(QAbstractItemView::ExtendedSelection);
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);
功能实现详解
1. 数据导入功能
void MainWindow::on_actionOpen_triggered()
{
// 使用文件对话框获取文件路径
QString fileName = QFileDialog::getOpenFileName(
this,
"打开一个文件",
QCoreApplication::applicationDirPath(),
"文本数据文件(*.txt);;所有文件(*.*)");
// 检查文件是否有效
if(fileName.isEmpty()) {
return;
}
// 打开文件并读取内容
QFile qFile(fileName);
if(!qFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
return;
}
// 使用文本流读取文件内容
QTextStream stream(&qFile);
QStringList fileContent;
// 逐行读取文件内容
while(!stream.atEnd()) {
QString line = stream.readLine();
fileContent.append(line);
ui->plainTextEdit->appendPlainText(line); // 在文本编辑器中显示
}
qFile.close(); // 关闭文件
// 使用读取的内容初始化数据模型
initModel(fileContent);
}
2. 数据模型初始化
void MainWindow::initModel(QStringList content)
{
// 读取表头行
QString headLine = content[0];
// 使用正则表达式分割表头(匹配一个或多个空白字符)
QStringList headList = headLine.split(QRegExp("\\s+"), QString::SkipEmptyParts);
model->setHorizontalHeaderLabels(headList); // 设置表头
// 处理数据行
int rows = content.count();
for(int i = 1; i < rows; i++) { // 从第1行开始(第0行是表头)
QString line = content[i];
QStringList fieldList = line.split(QRegExp("\\s+"), QString::SkipEmptyParts);
// 处理前5列普通数据
for(int j = 0; j < colCount - 1; j++) {
QStandardItem *item = new QStandardItem(fieldList[j]);
model->setItem(i - 1, j, item); // 设置单元格数据
}
// 处理最后一列(婚否列),设置为复选框
QStandardItem *item = new QStandardItem(headList[colCount - 1]);
item->setCheckable(true); // 设置为可勾选
// 根据文本内容设置复选框状态
if(fieldList[colCount - 1] == "否") {
item->setCheckState(Qt::Unchecked);
} else {
item->setCheckState(Qt::Checked);
}
model->setItem(i - 1, colCount - 1, item);
}
}
3. 状态栏显示优化
void MainWindow::on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
{
if(current.isValid()) {
auto item = model->itemFromIndex(current);
QString content;
// 特殊处理婚否列(最后一列)
if(current.column() == colCount - 1) {
// 根据复选框状态显示"是"或"否"
content = (item->checkState() == Qt::Checked) ? "是" : "否";
} else {
// 其他列直接显示文本内容
content = item->text();
}
// 更新状态栏信息
labelInfo->setText(QString::asprintf("当前单元格: %d行, %d列",
current.row(), current.column()) +
" 单元格内容: " + content);
// 更新粗体按钮状态
ui->actionBold->setChecked(item->font().bold());
}
}
完整代码实现
mainwindow.h 头文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QStandardItemModel>
#include <QItemSelectionModel>
#include <QLabel>
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_actionOpen_triggered(); // 打开文件
void on_actionSave_triggered(); // 保存文件
// 数据操作槽函数
void on_actionAppend_triggered(); // 尾部添加行
void on_actionInsert_triggered(); // 插入行
void on_actionDel_triggered(); // 删除行
void on_actionSee_triggered(); // 预览数据
// 格式设置槽函数
void on_actionAlignRight_triggered(); // 右对齐
void on_actionMiddle_triggered(); // 居中对齐
void on_actionLeft_triggered(); // 左对齐
void on_actionBold_triggered(bool checked); // 粗体设置
// 当前单元格变化槽函数
void on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous);
private:
Ui::MainWindow *ui; // UI对象指针
QStandardItemModel *model; // 数据模型
QItemSelectionModel *selectionModel; // 选择模型
int colCount; // 表格列数
QLabel *labelInfo; // 状态栏信息标签
// 初始化数据模型
void initModel(QStringList content);
};
#endif // MAINWINDOW_H
mainwindow.cpp 实现文件
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QTextStream>
// 构造函数
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this); // 设置UI
// 初始化状态栏信息标签
labelInfo = new QLabel(this);
statusBar()->addWidget(labelInfo);
// 初始化数据模型和选择模型
colCount = 6; // 设置表格列数
model = new QStandardItemModel(2, colCount, this); // 创建数据模型
selectionModel = new QItemSelectionModel(model); // 创建选择模型
// 设置表格视图的模型和选择模型
ui->tableView->setModel(model);
ui->tableView->setSelectionModel(selectionModel);
// 配置表格视图的选择模式和行为
ui->tableView->setSelectionMode(QAbstractItemView::ExtendedSelection); // 扩展选择模式
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems); // 选择单元格
// 连接当前单元格变化信号到槽函数
connect(selectionModel,
SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
this, SLOT(on_currentChanged(const QModelIndex &, const QModelIndex &)));
}
// 析构函数
MainWindow::~MainWindow()
{
delete ui; // 释放UI对象
}
// 打开文件槽函数
void MainWindow::on_actionOpen_triggered()
{
// 使用文件对话框获取文件路径
QString fileName = QFileDialog::getOpenFileName(
this,
"打开一个文件",
QCoreApplication::applicationDirPath(),
"文本数据文件(*.txt);;所有文件(*.*)");
// 检查文件是否有效
if(fileName.isEmpty()) {
return;
}
// 打开文件并读取内容
QFile qFile(fileName);
if(!qFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
return;
}
// 使用文本流读取文件内容
QTextStream stream(&qFile);
QStringList fileContent;
// 逐行读取文件内容
while(!stream.atEnd()) {
QString line = stream.readLine();
fileContent.append(line);
ui->plainTextEdit->appendPlainText(line); // 在文本编辑器中显示
}
qFile.close(); // 关闭文件
// 使用读取的内容初始化数据模型
initModel(fileContent);
}
// 初始化数据模型
void MainWindow::initModel(QStringList content)
{
// 读取表头行
QString headLine = content[0];
// 使用正则表达式分割表头(匹配一个或多个空白字符)
QStringList headList = headLine.split(QRegExp("\\s+"), QString::SkipEmptyParts);
model->setHorizontalHeaderLabels(headList); // 设置表头
// 处理数据行
int rows = content.count();
for(int i = 1; i < rows; i++) { // 从第1行开始(第0行是表头)
QString line = content[i];
QStringList fieldList = line.split(QRegExp("\\s+"), QString::SkipEmptyParts);
// 处理前5列普通数据
for(int j = 0; j < colCount - 1; j++) {
QStandardItem *item = new QStandardItem(fieldList[j]);
model->setItem(i - 1, j, item); // 设置单元格数据
}
// 处理最后一列(婚否列),设置为复选框
QStandardItem *item = new QStandardItem(headList[colCount - 1]);
item->setCheckable(true); // 设置为可勾选
// 根据文本内容设置复选框状态
if(fieldList[colCount - 1] == "否") {
item->setCheckState(Qt::Unchecked);
} else {
item->setCheckState(Qt::Checked);
}
model->setItem(i - 1, colCount - 1, item);
}
}
// 尾部添加行槽函数
void MainWindow::on_actionAppend_triggered()
{
// 初始化新行的默认值
QStringList initValue = {"无名", "男", "市场部", "销售", "5000", "婚否"};
QList<QStandardItem*> itemList;
// 创建新行的所有单元格
for(int i = 0; i < colCount; i++) {
QStandardItem *item = new QStandardItem(initValue[i]);
itemList.push_back(item);
}
// 设置最后一列为复选框
itemList[colCount - 1]->setCheckable(true);
// 在模型末尾插入新行
model->insertRow(model->rowCount(), itemList);
// 清除选择并选中新行
selectionModel->clearSelection();
QModelIndex index = model->index(model->rowCount() - 1, 0);
selectionModel->setCurrentIndex(index, QItemSelectionModel::Select);
}
// 插入行槽函数
void MainWindow::on_actionInsert_triggered()
{
// 初始化新行的默认值
QStringList initValue = {"无名", "男", "市场部", "销售", "5000", "婚否"};
QList<QStandardItem*> itemList;
// 创建新行的所有单元格
for(int i = 0; i < colCount; i++) {
QStandardItem *item = new QStandardItem(initValue[i]);
itemList.push_back(item);
}
// 设置最后一列为复选框
itemList[colCount - 1]->setCheckable(true);
// 获取当前选中位置并在该位置插入新行
QModelIndex index = selectionModel->currentIndex();
model->insertRow(index.row(), itemList);
// 清除选择并选中新插入的行
selectionModel->clearSelection();
selectionModel->setCurrentIndex(index, QItemSelectionModel::Select);
}
// 删除行槽函数
void MainWindow::on_actionDel_triggered()
{
// 获取当前选中位置
QModelIndex index = selectionModel->currentIndex();
// 如果是最后一行,直接删除
if(index.row() == model->rowCount() - 1) {
model->removeRow(index.row());
} else {
// 删除行并保持选中状态
model->removeRow(index.row());
selectionModel->setCurrentIndex(index, QItemSelectionModel::Select);
}
}
// 预览数据槽函数
void MainWindow::on_actionSee_triggered()
{
// 清空文本编辑器
ui->plainTextEdit->clear();
// 获取表头
QString str;
for(int i = 0; i < model->columnCount(); i++) {
QStandardItem *item = model->horizontalHeaderItem(i);
str += item->text() + "\t";
}
ui->plainTextEdit->appendPlainText(str); // 添加表头
// 获取每一行数据
for(int i = 0; i < model->rowCount(); i++) {
str = "";
for(int j = 0; j < model->columnCount(); j++) {
QStandardItem *item = model->item(i, j);
str += item->text() + "\t";
}
// 特殊处理婚否列
if(model->item(i, model->columnCount() - 1)->checkState() == Qt::Checked) {
str += "是";
} else {
str += "否";
}
ui->plainTextEdit->appendPlainText(str); // 添加数据行
}
}
// 保存文件槽函数
void MainWindow::on_actionSave_triggered()
{
// 使用文件对话框获取保存路径
QString fileName = QFileDialog::getSaveFileName(this, "保存文件",
QCoreApplication::applicationDirPath());
if(fileName.isEmpty()) {
return;
}
// 打开文件
QFile qFile(fileName);
if (!qFile.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) {
return;
}
// 使用文本流写入文件
QTextStream stream(&qFile);
// 写入表头
QString str;
for(int i = 0; i < model->columnCount(); i++) {
auto item = model->horizontalHeaderItem(i);
str += item->text() + "\t\t";
}
stream << str << "\n"; // 写入表头
// 写入数据行
for(int i = 0; i < model->rowCount(); i++) {
str = "";
for(int j = 0; j < model->columnCount(); j++) {
QStandardItem *item = model->item(i, j);
str += item->text() + "\t";
}
// 特殊处理婚否列
if(model->item(i, model->columnCount() - 1)->checkState() == Qt::Checked) {
str += "是";
} else {
str += "否";
}
stream << str << "\n"; // 写入数据行
}
qFile.close(); // 关闭文件
}
// 右对齐槽函数
void MainWindow::on_actionAlignRight_triggered()
{
// 检查是否有选中项
if(!selectionModel->hasSelection()) {
return;
}
// 获取所有选中项并设置右对齐
QModelIndexList indexList = selectionModel->selectedIndexes();
for(int i = 0; i < indexList.count(); i++) {
auto item = model->itemFromIndex(indexList[i]);
item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
}
}
// 居中对齐槽函数
void MainWindow::on_actionMiddle_triggered()
{
// 检查是否有选中项
if(!selectionModel->hasSelection()) {
return;
}
// 获取所有选中项并设置居中对齐
QModelIndexList indexList = selectionModel->selectedIndexes();
for(int i = 0; i < indexList.count(); i++) {
auto item = model->itemFromIndex(indexList[i]);
item->setTextAlignment(Qt::AlignCenter | Qt::AlignVCenter);
}
}
// 左对齐槽函数
void MainWindow::on_actionLeft_triggered()
{
// 检查是否有选中项
if(!selectionModel->hasSelection()) {
return;
}
// 获取所有选中项并设置左对齐
QModelIndexList indexList = selectionModel->selectedIndexes();
for(int i = 0; i < indexList.count(); i++) {
auto item = model->itemFromIndex(indexList[i]);
item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
}
}
// 粗体设置槽函数
void MainWindow::on_actionBold_triggered(bool checked)
{
// 检查是否有选中项
if(!selectionModel->hasSelection()) {
return;
}
// 获取所有选中项并设置粗体
QModelIndexList indexList = selectionModel->selectedIndexes();
for(int i = 0; i < indexList.count(); i++) {
auto item = model->itemFromIndex(indexList[i]);
QFont font = item->font();
font.setBold(checked);
item->setFont(font);
}
}
// 当前单元格变化槽函数
void MainWindow::on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
{
if(current.isValid()) {
auto item = model->itemFromIndex(current);
QString content;
// 特殊处理婚否列(最后一列)
if(current.column() == colCount - 1) {
// 根据复选框状态显示"是"或"否"
content = (item->checkState() == Qt::Checked) ? "是" : "否";
} else {
// 其他列直接显示文本内容
content = item->text();
}
// 更新状态栏信息
labelInfo->setText(QString::asprintf("当前单元格: %d行, %d列",
current.row(), current.column()) +
" 单元格内容: " + content);
// 更新粗体按钮状态
ui->actionBold->setChecked(item->font().bold());
}
}
总结
通过本文的详细介绍,我们学习了如何使用Qt的QStandardItemModel和QTableView开发一个功能完整的表格数据处理应用。关键点包括:
- 数据模型的使用:QStandardItemModel提供了灵活的数据存储和管理能力
- 表格视图的配置:通过设置选择模式和行为,实现丰富的交互体验
- 文件操作:实现了数据的导入和保存功能
- 数据操作:支持添加、插入和删除行操作
- 格式设置:实现了单元格的对齐和字体样式设置
- 状态栏显示:优化了婚否列的显示方式
更多推荐



所有评论(0)