学习《QT5.9 c++ 开发指南》第5章学习笔记3 QStandardItemModel
本章讲述了 QStandardItemModel 的使用方法,以及基本文件的读写。
QStandardItemModel 通常与QTabView 组合使用。
书上例子主要使用3个类:
QStandardItemModel : 基于项数据的标准数据模型,可以处理二维数据。维护一个二维的项数据数组,每一个项
都是QStandardItem 类的变量,用于存储数据,字体格式,对齐方式等。
QTabView : 二维数据表示图的组件,有多行与多列。
QItemSelectionModel : 用来跟踪视图组件的单元格选择的单元格选择状态的类,为单元格操作提供方便。
话不多说了,先看运行的结果图吧:
下面的是界面布局,与控件命名的图:
下图为Action编辑器所编辑的图:
有关action 添加这里就不细讲了,第4章节有详细讲解。
ok,接下来我们看看代码部分:
在mainWindow.h 文件中:
[code]#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QLabel> #include <QStandardItemModel> #include <QItemSelectionModel> #define FixedColumnCount 6 //文件固定6列 namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT private: QLabel *LabCurFile; //当前文件 QLabel *LabCellPos; //当前单元格行列号 QLabel *LabCellText; //当前单元格内容 QStandardItemModel *theModel;//数据模型 QItemSelectionModel *theSelection;//Item选择模型 void iniModelFormStringList(QStringList &); public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: void on_actFontBold_triggered(bool checked); void on_actAlignRight_triggered(); void on_actModelData_triggered(); void on_actOpen_triggered(); void on_actSave_triggered(); // void on_actAppend_triggered(); void on_actInsert_triggered(); void on_actDelete_triggered(); void on_actExit_triggered(); void on_actAlignLeft_triggered(); void on_actAlignCenter_triggered(); void on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H
其中 void on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous); 是手动添加,
自定义的 on_currentChanged(); 用于在TableView 上选择单元格的发生变化时,更新状态栏中的信息显示。
首先在cpp文件中添加对应的头文件
[code]#include <QFileDialog> #include <QTextStream>
1. 系统初始化部分
[code]MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); theModel = new QStandardItemModel(2,FixedColumnCount,this); //数据模型 theSelection = new QItemSelectionModel(theModel); //Item选择类型 //选择当前单元格变化时的信号与槽 connect(theSelection,SIGNAL(currentChanged(QModelIndex,QModelIndex)), this,SLOT(on_currentChanged(QModelIndex,QModelIndex))); //为tableView设置数据模型 ui->tableView->setModel(theModel);//设置数据模型 ui->tableView->setSelectionModel(theSelection); //设置选择模型 ui->tableView->setSelectionMode(QAbstractItemView::ExtendedSelection); ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems); setCentralWidget(ui->splitter); //创建状态栏组件 LabCurFile = new QLabel("当前文件",this); LabCurFile->setMinimumWidth(200); LabCellPos = new QLabel("当前单元格:",this); LabCellPos->setMinimumWidth(180); LabCellPos->setAlignment(Qt::AlignHCenter); LabCellText = new QLabel("单元格内容:",this); LabCellText->setMinimumWidth(180); ui->statusBar->addWidget(LabCurFile); ui->statusBar->addWidget(LabCellPos); ui->statusBar->addWidget(LabCellText); }
首先, theModel = new QStandardItemModel(2,FixedColumnCount,this);
选择为2行 6列的格式,然后通过 theSelection = new QItemSelectionModel(theModel);
把数据选择模型 与 theModel相互关联起来。
2. on_currentChanged()
[code]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 = theModel->itemFromIndex(current); this->LabCellText->setText("单元格内容: "+aItem->text()); QFont font = aItem->font(); ui->actFontBold->setChecked(font.bold()); } }
此函数过程主要显示状态栏中的数据.
3.准备好对应的文本文件:1.txt
[code]测深(m) 垂深(m) 方位(。) 总位移(m) 固井质量 测井取样 252 252 241.27 0.51 优 1 275 275 241.27 0.72 优 1 300 300 235.82 0.9 良 1 325 325 239.23 1.09 良 1 350 350 243.02 1.27 一般 1 375 375 245.25 1.48 一般 1 400 399.99 243.12 1.72 优 1 425 424.99 238.72 1.93 优 1 450 449.99 242.6 2.22 良 1 475 474.99 239.52 2.51 良 1 500 499.99 228.03 2.83 一般 0 525 524.99 237.27 3.21 一般 0 550 549.98 249.85 3.76 优 0 575 574.95 254.77 4.88 优 0 600 599.87 258.18 6.84 良 1 625 624.83 274.63 8.13 良 1 650 649.79 302.42 9.08 一般 1 675 674.79 344.37 9.14 一般 1 700 699.78 89.22 8.55 优 0 725 724.77 116.77 8.07 优 0 750 749.77 92.9 7.46 良 0 775 774.76 95.93 6.98 良 0 800 799.76 206.45 7.07 一般 0 825 824.76 206.45 7.17 一般 0 850 849.76 211.82 7.25 优 0
4.打开文件 按钮槽函数代码:
[code]void MainWindow::on_actOpen_triggered() { //打开文件 QString curPath = QCoreApplication::applicationFilePath(); //获取应用程序的路径 QString aFileName = QFileDialog::getOpenFileName(this,"打开一个文件", curPath,"井数据文件(*.txt);;所有文件(*.*)"); if(aFileName.isEmpty()) return; //如果未选择文件,退出 QStringList fFileContent;//文件内容字符串列表 QFile aFile(aFileName); if(aFile.open(QIODevice::ReadOnly|QIODevice::Text)) { QTextStream aStram(&aFile);//用文本流读取文件 ui->plainTextEdit->clear();//清空 while(!aStram.atEnd()) { QString str = aStram.readLine(); //读取文件的一行 ui->plainTextEdit->appendPlainText(str); //添加到文本框显示 fFileContent.append(str); //添加到 StringList } aFile.close();//关闭文件 this->LabCurFile->setText("当前文件:"+aFileName); //状态栏显示 ui->actAppend->setEnabled(true); //更新Actions的enable属性 ui->actInsert->setEnabled(true); ui->actDelete->setEnabled(true); ui->actSave->setEnabled(true); iniModelFormStringList(fFileContent); //从StringList的内容初始化数据模型 } }
这段的代码让用户选择需要打开的数据文本文件,然后只读和文本格式打开,逐行读取内容,在讲每行的字符串显示到界面
plainTextEdit里,并添加到一个临时的QStringList 类中,然后调用 iniModelFormStringList();
5.iniModelFormStringList()函数
[code]void MainWindow::iniModelFormStringList(QStringList & aFileContent) { //从一个StringList 获取数据,初始化数据Model int rowCnt = aFileContent.count(); //文本行数,第1行是标题 theModel->setSortRole(rowCnt-1);//实际数据行数 //设置表头 QString header = aFileContent.at(0); //第1行是表头 QStringList headerList = header.split(QRegExp("\\s+"),QString::SkipEmptyParts); theModel->setHorizontalHeaderLabels(headerList);//设置表头 //设置单元数据 int j = 0; QStandardItem *aItem; for (int i = 1;i<rowCnt;i++) { QString aLineText = aFileContent.at(i); //一个或多个空格、TAB等分隔符隔开的字符串, 分解为一个StringList QStringList tmpList = aLineText.split(QRegExp("\\s+"),QString::SkipEmptyParts); for (j = 0;j<FixedColumnCount -1;j++) //不需要最后一行 { aItem = new QStandardItem(tmpList.at(j)); theModel->setItem(i-1,j,aItem);//为模型的某个行列位置设置Item } aItem=new QStandardItem(headerList.at(j));//最后一列是Checkable,需要设置 aItem->setCheckable(true); //设置为Checkable if(tmpList.at(j)== "0" ) aItem->setCheckState(Qt::Unchecked); else aItem->setCheckState(Qt::Checked); theModel->setItem(i-1,j,aItem); } }
传进来的参数 aFileContent 是文本文件构成的所有StirngList,第1行是表头文字,数据在第2行开始。
6.添加行
[code]void MainWindow::on_actAppend_triggered() { //在表格最后添加行 QList<QStandardItem *> aItemList; //列表容器 QStandardItem *aItem; for (int i = 0;i<FixedColumnCount-1;i++) { aItem = new QStandardItem("0"); aItemList << aItem; } //获取最后一列的表头文字 QString str = theModel->headerData(theModel->columnCount()-1,Qt::Horizontal,Qt::DisplayRole).toString(); //创建 "测井取样"Item aItem = new QStandardItem(str); aItem->setCheckable(true); aItemList<<aItem; //添加到容器 theModel->insertRow(theModel->rowCount(),aItemList); //插入一行,需要每个Cell的Item QModelIndex curIndex = theModel->index(theModel->rowCount()-1,0);//创建最后一行的ModelIndex theSelection->clearSelection(); theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);//设置刚插入的行为当前选择行 }
7.插入行:
[code]void MainWindow::on_actInsert_triggered() { QList<QStandardItem *> aItemList; //列表容器 QStandardItem *aItem; for (int i = 0;i<FixedColumnCount-1;i++) { aItem = new QStandardItem("0"); aItemList << aItem; } //获取最后一列的表头文字 QString str = theModel->headerData(theModel->columnCount()-1,Qt::Horizontal,Qt::DisplayRole).toString(); //创建 "测井取样"Item aItem = new QStandardItem(str); aItem->setCheckable(true); aItemList<<aItem; //添加到容器 //插入到制定的 QModelIndex curIndex=theSelection->currentIndex(); //获取当前选中项的模型索引 theModel->insertRow(curIndex.row(),aItemList); theSelection->clearSelection();//清除已有选择 theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select); }
8.删除行:
[code]void MainWindow::on_actDelete_triggered() { QModelIndex curIndex = theSelection->currentIndex(); if(curIndex.row() == theModel->rowCount()-1) { theModel->removeRow(curIndex.row());//删除最后一行 } else { theModel->removeRow(curIndex.row());//删除一行,并重新设置当前选择行 theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select); } }
9.文字居左 居中 居右 :
[code]void MainWindow::on_actAlignLeft_triggered() { //左对齐 if(!theSelection->hasSelection())//没有选择的项 return; QModelIndexList selectedIndex = theSelection->selectedIndexes(); for (int i = 0; i<selectedIndex.count();i++) { QModelIndex aIndex = selectedIndex.at(i); //获取其中的一个模型索引 QStandardItem * aItem = theModel->itemFromIndex(aIndex); aItem->setTextAlignment(Qt::AlignLeft); } } void MainWindow::on_actAlignCenter_triggered() { if(!theSelection->hasSelection())//没有选择的项 return; QModelIndexList selectedIndex = theSelection->selectedIndexes(); for (int i = 0; i<selectedIndex.count();i++) { QModelIndex aIndex = selectedIndex.at(i); //获取其中的一个模型索引 QStandardItem * aItem = theModel->itemFromIndex(aIndex); aItem->setTextAlignment(Qt::AlignCenter); } } void MainWindow::on_actAlignRight_triggered() { if(!theSelection->hasSelection())//没有选择的项 return; QModelIndexList selectedIndex = theSelection->selectedIndexes(); for (int i = 0; i<selectedIndex.count();i++) { QModelIndex aIndex = selectedIndex.at(i); //获取其中的一个模型索引 QStandardItem * aItem = theModel->itemFromIndex(aIndex); aItem->setTextAlignment(Qt::AlignRight); } }
10.粗体:
[code]void MainWindow::on_actFontBold_triggered(bool checked) { //设置字体粗体 if (!theSelection->hasSelection()) return; //获取选择单元格的模型索引列表 QModelIndexList selectedIndex=theSelection->selectedIndexes(); for (int i=0;i<selectedIndex.count();i++) { QModelIndex aIndex=selectedIndex.at(i); //获取一个模型索引 QStandardItem* aItem=theModel->itemFromIndex(aIndex);//获取项数据 QFont font=aItem->font(); //获取字体 font.setBold(checked); //设置字体是否粗体 aItem->setFont(font); //重新设置字体 } }
11.模型导出:
[code]void MainWindow::on_actModelData_triggered() { //模型数据导出到PlainTextEdit显示 ui->plainTextEdit->clear(); //清空 QStandardItem *aItem; QString str = ""; //获取表头文字 int i,j; for (i=0;i<theModel->columnCount();i++) { // aItem=theModel->horizontalHeaderItem(i); //获取表头的一个项数据 str=str+aItem->text()+"\t"; //用TAB间隔文字 } ui->plainTextEdit->appendPlainText(str); //添加为文本框的一行 //获取数据区的每行 for (i=0;i<theModel->rowCount();i++) { str=""; for(j=0;j<theModel->columnCount()-1;j++) { aItem = theModel->item(i,j); str=str+aItem->text()+QString::asprintf("\t"); //以 TAB分隔 } aItem=theModel->item(i,j); //最后一行是逻辑型 if (aItem->checkState()==Qt::Checked) str=str+"1"; else str=str+"0"; ui->plainTextEdit->appendPlainText(str); } }
12.文件另存为:
[code]void MainWindow::on_actSave_triggered() { //保存为文件 QString curPath = QCoreApplication::applicationDirPath(); QString aFileName = QFileDialog::getSaveFileName(this,"选择一个文件",curPath, "井斜数据文件(*.txt);;所有文件(*.*)"); if(aFileName.isEmpty()) //未选择文件,退出 return; QFile aFile; if(!(aFile.open(QIODevice::ReadWrite|QIODevice::Text|QIODevice::Truncate))) //Truncate 截短的 return; //以读写、覆盖原有内容方式打开文件 QTextStream aStream(&aFile); //用文本流读取文件 QStandardItem *aItem; int i,j; QString str=""; ui->plainTextEdit->clear(); //获取表头文字 for (i = 0;i < theModel->columnCount(); i++) { aItem = theModel->horizontalHeaderItem(i); //获取表头的项数据 str=str+aItem->text()+"\t\t"; //以TAB见隔开 } aStream << str << "\n"; //文件里需要加入换行符 \n ui->plainTextEdit->appendPlainText(str); //获取数据区域的文字 for (i=0;i<theModel->rowCount();i++) { str=""; for(j=0;j<theModel->columnCount()-1;j++) { aItem = theModel->item(i,j); str=str+aItem->text()+QString::asprintf("\t"); //以 TAB分隔 } aItem=theModel->item(i,j); //最后一行是逻辑型 if (aItem->checkState()==Qt::Checked) str=str+"1"; else str=str+"0"; ui->plainTextEdit->appendPlainText(str); aStream << str << "\n"; } }
已上就是全部的函数功能模块了,仔细看看对应的函数,对以后会有很大的进步,文件已经上传,需要的小伙伴可以下载,
让我们一起加油与进步。
- 点赞 1
- 收藏
- 分享
- 文章举报
- 学习《QT5.9 c++ 开发指南》第6章 标准对话框
- 学习Qt5.9 C++开发指南
- 《Qt5.9 C++开发指南》第3章(共16章)解读
- ATL开发指南学习笔记: COM与C++的VTable(虚拟表)
- 《Qt5.9 C++开发指南》第2章(共16章)解读
- Inside the C++ Object Model学习笔记[Chap6]
- Qt Model/View 学习笔记
- Inside the C++ Object Model学习笔记[Chap2.2]
- Qt Model/View 学习笔记 (六)
- Qt Model/View 学习笔记 (四) 创建新的Models
- Qt Model/View 学习笔记 一
- Inside the C++ Object Model学习笔记[Chap3.4]
- Qt Model/View 学习笔记 (七)
- Qt Model/View 学习笔记 (五)
- Qt Model/View 学习笔记 (二)
- Qt Model/View 学习笔记 (五) View 类
- Inside the C++ Object Model 学习笔记 第四章 函数语意学
- Qt Model/View 学习笔记 (三)
- Qt Model/View 学习笔记 (五)
- gtk学习笔记1(安装c/c++和gtk开发环境)