Qt:26---QStandardItemModel数据模型
原创
©著作权归作者所有:来自51CTO博客作者董哥的黑板报的原创作品,请联系作者获取转载授权,否则将追究法律责任
一、QStandardItemModel类的基本功能
- QStandardItemModel是标准的以项数据为基础的标准数据模型类
- QStandardItemModel通常与QTableView组合成数据模型,实现通用的二维数据的管理功能
- QStandardItemModel维护一个二维的项数据数组,每个项是一个QStandarItem类对象,用于存储项的数据、字体格式、对齐方式等
二、QItemSelectionModel类
- 概念:一个用于跟踪视图组件的单元格选择状态的类。QTableView与QStandardItemModel数据模型组合后,在QTableView选择某个/多个单元格后,这些单元格就组合成一个QItemSelectionModel类对象
- 是一个选择模型
三、QModelIndex、QModelIndexList类
- QModelIndex:获得当前数据模型的索引,通过QModelIndex QStandardItemModel::index(int row, int column, const QModelIndex &parent = QModelIndex()) const、QModelIndex QItemSelectionModel::currentIndex() const函数获取,或者QModelIndexList的at函数获取
- QModelIndexList:获得当前数据模型的索引集合,通过QModelIndexList QItemSelectionModel::selectedIndexes() const函数获得
四、常用函数
//通过数据模型索引获得QStandardItem 对象
QStandardItem *QStandardItemModel::itemFromIndex(const QModelIndex &index) const
//为QStandardItemModel数据模型设置表头
void QStandardItemModel::setHorizontalHeaderLabels(const QStringList &labels)
//为QStandardItemModel数据模型的指定行、列设置QStandardItem对象
void QStandardItemModel::setItem(int row, int column, QStandardItem *item)
//将QStandardItem对象设置为CheckBox状态(选中/未选中)
void QStandardItem::setCheckState(Qt::CheckState state)
//获取表头数据
QVariant QStandardItemModel::headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const
//在row行之前插入一个QList集合的对象
void QStandardItemModel::insertRow(int row, const QList<QStandardItem *> &items)
五、演示案例
功能实现
工具栏使用到的Action
类的定义
类构造函数
on_currentChanged槽函数
void MainWindow::on_currentChanged(const QModelIndex ¤t,const QModelIndex &previous)
{
if(current.isValid())
{
LabCellPos->setText(QString::asprintf("current:%d row,%d col",current.row(),current.column()));
QStandardItem* aItem=theModel->itemFromIndex(current);
this->LabCellText->setText("Current content:"+aItem->text());
QFont font=aItem->font();
ui->actFontBold->setChecked(font.bold());
}
}
文件打开triggered函数、与自定义函数iniModelFromStringList
- 文件打开triggered的函数会打开一个已经书写规范的文件,然后读取这些文件的数据,存放在一个QStringList对象中,然后将QStringList对象作为iniModelFromStringList函数的参数调用该函数,然后iniModelFromStringList将这些数据显示到tabView中
- 最后一列“测井取样”为布尔值,在设置tabView时,我们将最后一列设置为CheckBox对象
- QString::split()函数用来分割成一个QString对象分割为QStringList对象
void MainWindow::on_actOpen_triggered()
{
QString curPath=QCoreApplication::applicationDirPath();
QString aFileName=QFileDialog::getOpenFileName(this,
QStringLiteral("打开一个文件"),curPath,QStringLiteral("井数据文件(*.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();
this->LabCurFile->setText(QStringLiteral("当前文件:")+aFileName);
iniModelFromStringList(fFileContent);
}
}
void MainWindow::iniModelFromStringList(QStringList &aFileContent)
{
int rowCnt=aFileContent.count();
theModel->setRowCount(rowCnt-1);
QString header=aFileContent.at(0);
QStringList headerList=header.split(QRegExp("\\s+"),QString::SkipEmptyParts);
theModel->setHorizontalHeaderLabels(headerList);
QStandardItem* aItem;
QStringList tmpList;
int j;
for(int i=1;i<rowCnt;++i)
{
QString aLineText=aFileContent.at(i);
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);
}
aItem=new QStandardItem(headerList.at(j));
aItem->setCheckable(true);
if(tmpList.at(j)=="0")
aItem->setCheckState(Qt::Unchecked);
else
aItem->setCheckState(Qt::Checked);
theModel->setItem(i-1,j,aItem);
}
}
添加行按钮触发函数(act_Append_triggered)
- void QStandardItemModel::insertRow(int row, const QList<QStandardItem *> &items) //该函数在row行之前插入一行数据,数据为参数2QList的集合
- void QStandardItemModel::insertRow(int row, QStandardItem *item) //该函数在row行之前插入一个QStandardItem对象
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();
aItem=new QStandardItem(str);
aItem->setCheckable(true);
aItemList<<aItem;
theModel->insertRow(theModel->rowCount(),aItemList);
QModelIndex curIndex=theModel->index(theModel->rowCount()-1,0);
theSelection->clearSelection();
theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);
}
插入行按钮触发函数(actInsert_triggered)
- 与添加行按钮的代码类似,只是将insertRow的参数1改为当前选择的索引即可,就是在当前的索引处插入一行新数据
删除行按钮触发函数(actDelete_triggered)
- bool QAbstractItemModel::removeRow(int row, const QModelIndex &parent = QModelIndex()) //删除指定的行
- 下面的代码为什么要判断是否为最后一行,因为QStandardItemModel数据模型刚打开的时候是没有处于选择状态的
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);
}
}
居左、居中、居右按钮触发函数(actAlignLeft_triggered)
- setTextAlignment() //用来这是QStandardItem对象的对齐方式
- 下面只演示向左对齐的,居中与向右对齐只需要改变setTextAlignment函数的参数即可
void MainWindow::on_actAlignLeft_triggered()
{
if(!theSelection->hasSelection())
return;
QModelIndexList selectIndex=theSelection->selectedIndexes();
for(int i=0;i<selectIndex.count();++i)
{
QModelIndex aIndex=selectIndex.at(i);
QStandardItem* aItem=theModel->itemFromIndex(aIndex);
aItem->setTextAlignment(Qt::AlignLeft);
}
}
粗体按钮触发函数(actFontBold_triggered)
- void QStandardItem::setFont(const QFont &font) //设置项的字体格式
void MainWindow::on_actFontBold_triggered()
{
if(!theSelection->hasSelection())
return;
QModelIndexList selectIndex=theSelection->selectedIndexes();
for(int i=0;i<selectIndex.count();++i)
{
QModelIndex aIndex=selectIndex.at(i);
QStandardItem* aItem=theModel->itemFromIndex(aIndex);
QFont font=aItem->font();
font.setBold(true);
aItem->setFont(font);
}
}
另存文件按钮触发函数(actSave_triggered)
- 点击该按钮,可以将数据模型的数据另存为一个数据文本文件,同时也显示在PlainTextEdit里
- 注意:该函数还有问题,待解决
void MainWindow::on_actSave_triggered()
{
QString curPath=QCoreApplication::applicationDirPath();
QString aFileName=QFileDialog::getSaveFileName(this,QStringLiteral("选择一个文件"),
curPath,QStringLiteral("井斜数据文件(*.txt);;所有文件(*.*)"));
if(aFileName.isEmpty())
return;
QFile aFile(aFileName);
if(!(aFile.open(QIODevice::ReadWrite|QIODevice::Text|QIODevice::Truncate)))
return;
QTextStream aStream(&aFile);
QStandardItem* aItem;
int i,j;
QString str;
ui->plainTextEdit->clear();
for(int i=0;i>theModel->columnCount();++i)
{
aItem=theModel->horizontalHeaderItem(i);
str=str+aItem->text()+"\t";
}
aStream<<str<<"\n";
ui->plainTextEdit->appendPlainText(str);
for(i=0;i<theModel->rowCount();++i)
{
str="";
for(j=0;i<theModel->columnCount()-1;j++)
{
aItem=theModel->item(i,j);
str=str+aItem->text()+QString::asprintf("\t");
}
aItem=theModel->item(i,j);
if(aItem->checkState()==Qt::Checked)
str=str+"1";
else
str=str+"0";
ui->plainTextEdit->appendPlainText(str);
aStream<<str<<"\n";
}
}
数据模型预览按钮触发函数
- 与数据另存为文件按钮的功能类似,就是将数据模型的数据显示到右侧的PlainTextEdit里面