QStandardItemModel的使用
实现功能:
打开一个文本文件,该文件为二维数据文件,通过字符串处理获取表头和各行各列数据,导入到QStandardItemModel数据模型
编辑修改数据模型的数据
设置数据模型中某项的不同角色的数据
通过QItemSelectionModel获取视图组件上当前单元格
将数据模型中的数据显示到QPlainTextEdit组件中
将修改后的数据模型另存为一个文本文件
mainwindow.h文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
#include <QStandardItemModel>
#include <QItemSelectionModel>
namespace Ui {
class MainWindow;
}
#define FixedColumCount 6 //固定列数为6
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
QLabel *LabCurFile;//表示当前文件
QLabel *LabCellPos;//当前单元格行列号
QLabel *LabCellText;//当前单元格内容
QStandardItemModel *theModel;//加入头文件<QStandardItemModel>
//数据模型
QItemSelectionModel *theSelection;//加入头文件<QItemSelectionModel>
//选择数据模型
void iniModelFromStringList(QStringList&);//从StringList初始化数据模型
private slots:
//自定义槽函数
void on_currentChanged(const QModelIndex ¤t,const QModelIndex &previous);
void on_actOpen_triggered();
void on_actAppend_triggered();
void on_actInsert_triggered();
void on_actDelete_triggered();
void on_actAlignLeft_triggered();
void on_actAlignCenter_triggered();
void on_actAlignRight_triggered();
void on_actFontBold_triggered();
void on_actFontBold_triggered(bool checked);
void on_actModelData_triggered();
void on_actSave_triggered();
};
#endif // MAINWINDOW_H
mainwindow.cpp文件
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTableView>
#include <QFileDialog>
#include <QTextStream>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//进行界面初始化,数据模型和选择模型的创建,信号与槽的关联
setCentralWidget(ui->splitter);
theModel=new QStandardItemModel(2,FixedColumCount,this);//2*6的数据模型
theSelection=new QItemSelectionModel(theModel);//选择模型
connect(theSelection,SIGNAL(currentChanged(QModelIndex,QModelIndex)),this,SLOT(on_currentChanged(QModelIndex,QModelIndex)));
//Selection的currentChanged信号()与on_currentChanged()关联
ui->tableView->setModel(theModel);
ui->tableView->setSelectionModel(theSelection);
ui->tableView->setSelectionMode(QAbstractItemView::ExtendedSelection);//允许选中多行
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);//设置选择模式为单元格
//状态栏标签
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);
}
MainWindow::~MainWindow()
{
delete ui;
}
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;
ui->actFontBold->setChecked(font.bold());//更新actFontBold的check状态
}
}
void MainWindow::on_actOpen_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);//以文本流读取文件
//加入头文件<QTextStream>
ui->plainTextEdit->clear();//清空
while (!aStream.atEnd())
{
QString str=aStream.readLine();//读取文件的一行
ui->plainTextEdit->appendPlainText(str); //添加到文本框显示
fFileContent.append(str); //添加到 StringList
}
aFile.close();//关闭文件
this->LabCurFile->setText("当前文件:"+aFileName);//状态栏显示
//更新Actions的enable属性
ui->actAppend->setEnabled(true);
ui->actInsert->setEnabled(true);
ui->actDelete->setEnabled(true);
ui->actSave->setEnabled(true);
iniModelFromStringList(fFileContent);//初始化数据模型
}
}
void MainWindow::iniModelFromStringList(QStringList& aFileContent)//从一个StringList 获取数据,初始化数据Model
{
int rowCnt=aFileContent.count(); //获取文本行数,其中第1行是标题
theModel->setRowCount(rowCnt-1); //实际数据行数
//设置表头
QString header=aFileContent.at(0);//第1行是表头
//一个或多个空格、TAB等分隔符隔开的字符串, 分解为一个StringList
QStringList headerList=header.split(QRegExp("\\s+"),QString::SkipEmptyParts);
theModel->setHorizontalHeaderLabels(headerList); //设置表头文字
//设置表格数据
int j;
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<FixedColumCount-1;j++) //tmpList的行数等于FixedColumnCount, 固定的
{ //不包含最后一列
aItem=new QStandardItem(tmpList.at(j));//创建item
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); //根据数据设置check状态
else
aItem->setCheckState(Qt::Checked);
theModel->setItem(i-1,j,aItem); //为模型的某个行列位置设置Item
}
}
void MainWindow::on_actAppend_triggered()//在最后添加行
{
QList<QStandardItem*> aItemList;//列表类
QStandardItem *aItem;
for(int i=0;i<FixedColumCount-1;i++)//不包含最后一列
{
aItem=new QStandardItem("未知");//创建Item为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);//改变选中的单元格为添加行的第一个单元格
}
void MainWindow::on_actInsert_triggered()//插入行
{
QList<QStandardItem*> aItemList;//列表类
QStandardItem *aItem;
for(int i=0;i<FixedColumCount-1;i++)//不包含最后一列
{
aItem=new QStandardItem("未知1");//创建Item为0
aItemList<<aItem;//添加到列表
}
//获取最后一列的表头文字
QString str=theModel->headerData(theModel->columnCount()-1,Qt::Horizontal,Qt::DisplayRole).toString();//获取表头
aItem=new QStandardItem(str);
aItem->setCheckable(true);
aItemList<<aItem;//添加到列表
QModelIndex curIndex=theSelection->currentIndex();//获取当前的索引
theModel->insertRow(curIndex.row(),aItemList);//在当前行插入新行
curIndex=theModel->index(curIndex.row(),0);
theSelection->clearSelection();
theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);//改变选中的单元格为插入行的第一个单元格
}
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);//重新设置选中行
}
}
void MainWindow::on_actAlignLeft_triggered()//左对齐
{
if(!theSelection->hasSelection())
return;
//获取选中的单元格的模型索引列表
QModelIndexList selectedIndex=theSelection->selectedIndexes();
for(int i=0;i<selectedIndex.count();i++)
{
QModelIndex index=selectedIndex.at(i);//获取一个模型索引
QStandardItem *aItem=theModel->itemFromIndex(index);//通过索引值获取对象
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 index=selectedIndex.at(i);//获取一个模型索引
QStandardItem *aItem=theModel->itemFromIndex(index);//通过索引值获取对象
aItem->setTextAlignment(Qt::AlignHCenter);//设置为左对齐
}
}
void MainWindow::on_actAlignRight_triggered()//右对齐
{
if(!theSelection->hasSelection())
return;
QModelIndexList selectedIndex=theSelection->selectedIndexes();
for(int i=0;i<selectedIndex.count();i++)
{
QModelIndex index=selectedIndex.at(i);//获取一个模型索引
QStandardItem *aItem=theModel->itemFromIndex(index);//通过索引值获取对象
aItem->setTextAlignment(Qt::AlignRight);//设置为右对齐
}
}
void MainWindow::on_actFontBold_triggered()
{
}
void MainWindow::on_actFontBold_triggered(bool checked)//设置为粗体
{
if(!theSelection->hasSelection())
{
return;
}
QModelIndexList selectedIndex=theSelection->selectedIndexes();
for(int i=0;i<selectedIndex.count();i++)
{
QModelIndex index=selectedIndex.at(i);//获取一个模型索引
QStandardItem *aItem=theModel->itemFromIndex(index);//通过索引值获取对象
QFont font=aItem->font();
font.setBold(checked);//设置为粗体
aItem->setFont(font);
}
}
void MainWindow::on_actModelData_triggered()//数据模型预览
{
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);
}
}
void MainWindow::on_actSave_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 *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\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";
}
}