QStandardItemModel 是标准的以项数据为单位的基于M/V模型的一种标准数据管理方式,Model/View 是Qt中的一种数据编排结构,其中Model代表模型,View代表视图,视图是显示和编辑数据的界面组件,而模型则是视图与原始数据之间的接口,通常该类结构都是用在数据库中较多,例如模型结构负责读取或写入数据库,视图结构则负责展示数据,其条理清晰,编写代码便于维护。
QStandardItemModel组件通常会配合TableView
组件一起使用,当数据库或文本中的记录发生变化时会自动同步到组件中,首先绘制UI界面。

其次绑定顶部ToolBar
菜单,分别对菜单增加对应的功能属性的描述等。

初始化构造函数: 当程序运行时,我们需要对页面中的控件逐一初始化,并将Table表格与模型通过调用ui->tableView->setModel(model)
进行绑定。
#include "mainwindow.h" #include "ui_mainwindow.h"
#include <iostream> #include <QLabel> #include <QStandardItem> #include <QItemSelectionModel>
#include <QFileDialog> #include <QTextStream>
#include <QList>
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this);
model = new QStandardItemModel(3,FixedColumnCount,this); selection = new QItemSelectionModel(model);
ui->tableView->setModel(model); ui->tableView->setSelectionModel(selection);
ui->actionSave->setEnabled(false); ui->actionView->setEnabled(false); ui->actionAppend->setEnabled(false); ui->actionDelete->setEnabled(false); ui->actionInsert->setEnabled(false);
LabCurFile = new QLabel("当前文件:",this); LabCurFile->setMinimumWidth(200);
LabCellPos = new QLabel("当前单元格:",this); LabCellPos->setMinimumWidth(180); LabCellPos->setAlignment(Qt::AlignHCenter);
LabCellText = new QLabel("单元格内容:",this); LabCellText->setMinimumWidth(150);
ui->statusbar->addWidget(LabCurFile); ui->statusbar->addWidget(LabCellPos); ui->statusbar->addWidget(LabCellText);
connect(selection,SIGNAL(currentChanged(QModelIndex,QModelIndex)),this,SLOT(on_currentChanged(QModelIndex,QModelIndex))); }
MainWindow::~MainWindow() { delete ui; }
|
初始化时同时需要绑定一个on_currentChanged(QModelIndex,QModelIndex)
信号,当用户选中指定单元格时相应用户。
void MainWindow::on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { Q_UNUSED(previous);
if (current.isValid()) { LabCellPos->setText(QString::asprintf("当前单元格:%d行,%d列",current.row(),current.column())); QStandardItem *aItem; aItem=model->itemFromIndex(current); this->LabCellText->setText("单元格内容:"+aItem->text()); } }
|
当页面被初始化时,默认界面如下:

打开并填充组件: 当工具栏中打开文件被点击后则触发,打开文件时通过aFile.open
打开,循环读入文件,并将文件中的内容逐行追加到QStringList fFileContent
中,当追加完毕后,直接调用iniModelFromStringList(fFileContent);
完成对页面TableView组件的初始化,并设置其他控件状态为可点击。
void MainWindow::on_actionOpen_triggered() { QString curPath=QCoreApplication::applicationDirPath(); QString aFileName=QFileDialog::getOpenFileName(this,"打开一个文件",curPath,"数据文件(*.txt);;所有文件(*.*)"); if (aFileName.isEmpty()) { return; }
QStringList fFileContent; QFile aFile(aFileName); if (aFile.open(QIODevice::ReadOnly | QIODevice::Text)) { QTextStream aStream(&aFile); ui->plainTextEdit->clear();
while (!aStream.atEnd()) { QString str=aStream.readLine(); ui->plainTextEdit->appendPlainText(str); fFileContent.append(str); } aFile.close();
iniModelFromStringList(fFileContent); }
ui->actionSave->setEnabled(true); ui->actionView->setEnabled(true); ui->actionAppend->setEnabled(true); ui->actionDelete->setEnabled(true); ui->actionInsert->setEnabled(true);
this->LabCurFile->setText("当前文件:"+aFileName); }
|
如上iniModelFromStringList(fFileContent);
函数是后期增加的,我们需要自己实现,该函数的作用是从传入的StringList
中获取数据,并将数据初始化到TableView
模型中,实现代码如下。
void MainWindow::iniModelFromStringList(QStringList& aFileContent) { int rowCnt=aFileContent.count(); model->setRowCount(rowCnt-1);
QString header=aFileContent.at(0);
QStringList headerList=header.split(QRegExp("\\s+"),QString::SkipEmptyParts); model->setHorizontalHeaderLabels(headerList);
int x = 0,y = 0; QStandardItem *Item;
for(x=1; x < rowCnt; x++) { QString LineText = aFileContent.at(x);
QStringList tmpList=LineText.split(QRegExp("\\s+"),QString::SkipEmptyParts);
for(y=0; y < FixedColumnCount-1; y++) { Item = new QStandardItem(tmpList.at(y)); model->setItem(x-1,y,Item); }
Item=new QStandardItem(headerList.at(y)); Item->setCheckable(true);
if (tmpList.at(y) == "0") Item->setCheckState(Qt::Unchecked); else Item->setCheckState(Qt::Checked);
model->setItem(x-1,y,Item); } }
|
初始化组件后效果如下:

实现添加一行数据: 为TableView添加一行数据,在文件末尾插入。
void MainWindow::on_actionAppend_triggered() { QList<QStandardItem *> ItemList; QStandardItem *Item;
for(int x=0; x<FixedColumnCount-1; x++) { Item = new QStandardItem("测试(追加行)"); ItemList << Item; }
QString str = model->headerData(model->columnCount()-1,Qt::Horizontal,Qt::DisplayRole).toString();
Item=new QStandardItem(str); Item->setCheckable(true); ItemList << Item;
model->insertRow(model->rowCount(),ItemList); QModelIndex curIndex=model->index(model->rowCount()-1,0);
selection->clearSelection(); selection->setCurrentIndex(curIndex,QItemSelectionModel::Select); }
|
插入代码演示效果:

实现插入一行数据: 为TableView插入一行数据(在文件任意位置插入数据)
void MainWindow::on_actionInsert_triggered() { QList<QStandardItem*> ItemList; QStandardItem *Item;
for(int i=0;i<FixedColumnCount-1;i++) { Item= new QStandardItem("测试(插入行)"); ItemList << Item; }
QString str; str=model->headerData(model->columnCount()-1,Qt::Horizontal,Qt::DisplayRole).toString(); Item=new QStandardItem(str); Item->setCheckable(true); ItemList<<Item;
QModelIndex curIndex=selection->currentIndex(); model->insertRow(curIndex.row(),ItemList); selection->clearSelection(); selection->setCurrentIndex(curIndex,QItemSelectionModel::Select); }
|
插入代码演示效果:

实现删除一行数据: 删除数据之前需要通过selection->currentIndex()
确定当前选中行,并通过model->removeRow()
移除即可。
void MainWindow::on_actionDelete_triggered() { QModelIndex curIndex = selection->currentIndex();
if (curIndex.row()==model->rowCount()-1) { model->removeRow(curIndex.row()); } else { model->removeRow(curIndex.row()); selection->setCurrentIndex(curIndex,QItemSelectionModel::Select); } }
|
删除代码效果演示:

实现字体数据对齐: 表格中的字体可以实现多种对其方式,对齐方式分为 居中对齐,左对齐,右对齐 三种。
void MainWindow::on_pushButton_clicked() { if (!selection->hasSelection()) return;
QModelIndexList selectedIndex=selection->selectedIndexes();
QModelIndex Index; QStandardItem *Item;
for (int i=0; i<selectedIndex.count(); i++) { Index=selectedIndex.at(i); Item=model->itemFromIndex(Index); Item->setTextAlignment(Qt::AlignHCenter); } }
void MainWindow::on_pushButton_2_clicked() { if (!selection->hasSelection()) return;
QModelIndexList selectedIndex=selection->selectedIndexes();
for (int i=0;i<selectedIndex.count();i++) { QModelIndex aIndex=selectedIndex.at(i); QStandardItem* aItem=model->itemFromIndex(aIndex); aItem->setTextAlignment(Qt::AlignLeft); } }
void MainWindow::on_pushButton_3_clicked() { if (!selection->hasSelection()) return;
QModelIndexList selectedIndex=selection->selectedIndexes();
QModelIndex aIndex; QStandardItem *aItem;
for (int i=0;i<selectedIndex.count();i++) { aIndex=selectedIndex.at(i); aItem=model->itemFromIndex(aIndex); aItem->setTextAlignment(Qt::AlignRight); } }
|
对齐代码效果演示:

实现字体数据加粗: 将选中行的字体进行加粗显示。
void MainWindow::on_pushButton_4_clicked() { if (!selection->hasSelection()) return;
QModelIndexList selectedIndex=selection->selectedIndexes();
for (int i=0;i<selectedIndex.count();i++) { QModelIndex aIndex=selectedIndex.at(i); QStandardItem* aItem=model->itemFromIndex(aIndex); QFont font=aItem->font(); font.setBold(true); aItem->setFont(font); } }
|
加粗代码效果演示:

实现保存文件: 当保存文件被点击后触发,通过便利TableWidget模型组件中的数据,并将数据通过aStream << str << "\n";
写出到记事本中。
void MainWindow::on_actionSave_triggered() { QString curPath=QCoreApplication::applicationDirPath();
QString aFileName=QFileDialog::getSaveFileName(this,tr("选择一个文件"),curPath,"数据文件(*.txt);;所有文件(*.*)");
if (aFileName.isEmpty()) return;
QFile aFile(aFileName);
if (!(aFile.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate))) return;
QTextStream aStream(&aFile); QStandardItem *Item; QString str; int x = 0,y = 0;
ui->plainTextEdit->clear();
for (x=0; x<model->columnCount(); x++) { Item=model->horizontalHeaderItem(x); str= str + Item->text() + "\t\t"; } aStream << str << "\n"; ui->plainTextEdit->appendPlainText(str);
for ( x=0; x < model->rowCount(); x++) { str = ""; for( y=0; y < model->columnCount()-1; y++) { Item=model->item(x,y); str=str + Item->text() + QString::asprintf("\t\t"); }
Item=model->item(x,y); if (Item->checkState()==Qt::Checked) str= str + "1"; else str= str + "0";
ui->plainTextEdit->appendPlainText(str); aStream << str << "\n"; } }
void MainWindow::on_actionView_triggered() { ui->plainTextEdit->clear(); QStandardItem *Item; QString str;
int x=0,y=0; for (x=0; x<model->columnCount(); x++) { Item=model->horizontalHeaderItem(x); str= str + Item->text() + "\t"; } ui->plainTextEdit->appendPlainText(str);
for (x=0; x<model->rowCount(); x++) { str=""; for(y=0; y<model->columnCount()-1; y++) { Item=model->item(x,y); str= str + Item->text() + QString::asprintf("\t"); }
Item=model->item(x,y); if (Item->checkState()==Qt::Checked) str= str + "1"; else str= str + "0";
ui->plainTextEdit->appendPlainText(str); } }
|
文件保存后如下:
