您的位置:首页 > 编程语言 > C语言/C++

学习《QT5.9 c++ 开发指南》第5章学习笔记3 QStandardItemModel

2020-02-03 08:47 896 查看

本章讲述了  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 &current, const QModelIndex &previous);

private:
Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

其中   void on_currentChanged(const QModelIndex &current, 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 &current, 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
  • 收藏
  • 分享
  • 文章举报
比卡丘不皮 发布了10 篇原创文章 · 获赞 4 · 访问量 3324 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: