目录
1 概述
2 常用方法
3 QStandardItemModel的使用
3.1 界面设计与主窗口类定义
3.2 系统初始化
3.3 从文本文件导入数据
3.4 数据修改
3.5 单元格格式设置
3.6 数据另存为文件
1 概述
-
QStandardItemModel:基于项数据的标准数据模型,可以处理二维数据。维护一个二维的项数 数组,每个项是一个 QStandardltem 类的变量,用于存储项的数据、字体格式、对齐方式等。
-
QTableView:二维数据表视图组件,有多个行和多个列,每个基本显示单元是一个单元格,通过setModel()函数设置一个QStandardItemModel类的数据模型之后,一个单元格显示QStandardItemModel数据模型中的一个项。
-
QItemSelectionModel:一个用于跟踪视图组件的单元格选择状态的类,当在QTableView选择某个单元格,或多个单元格时,通过QItemSelectionModel可以获得选中的单元格的 模型索引,为单元格的选择操作提供方便。
QStandardItemModel model;
QStandardItem *parentItem = model.invisibleRootItem();
for (int i = 0; i < 4; ++i) {
QStandardItem *item = new QStandardItem(QString("item %0").arg(i));
parentItem->appendRow(item);
parentItem = item;
}
QStandardItemModel model(4, 4);
for (int row = 0; row < 4; ++row) {
for (int column = 0; column < 4; ++column) {
QStandardItem *item = new QStandardItem(QString("row %0, column %1").arg(row).arg(column));
model.setItem(row, column, item);
}
}
QTreeView *treeView = new QTreeView(this);
treeView->setModel(myStandardItemModel);
connect(treeView, SIGNAL(clicked(QModelIndex)),
this, SLOT(clicked(QModelIndex)));
void MyWidget::clicked(const QModelIndex &index)
{
QStandardItem *item = myStandardItemModel->itemFromIndex(index);
}
treeView->scrollTo(item->index());
2 常用方法
-
void QStandardItemModel::appendColumn(const QList<QStandardItem *> &items):
-
void QStandardItemModel::appendRow(const QList<QStandardItem *> &items):
-
void QStandardItemModel::appendRow(QStandardItem *item):
-
void QStandardItemModel::clear():
-
[virtual] int QStandardItemModel::columnCount(const QModelIndex &parent = QModelIndex()) const:
-
[virtual] QVariant QStandardItemModel::data(const QModelIndex &index, int role = Qt::DisplayRole) const:
-
[virtual] bool QStandardItemModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent):
-
QList<QStandardItem *> QStandardItemModel::findItems(const QString &text, Qt::MatchFlags flags = Qt::MatchExactly, int column = 0) const:
-
[virtual] Qt::ItemFlags QStandardItemModel::flags(const QModelIndex &index) const:
-
[virtual] bool QStandardItemModel::hasChildren(const QModelIndex &parent = QModelIndex()) const:
-
[virtual] QVariant QStandardItemModel::headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const:
-
QStandardItem *QStandardItemModel::horizontalHeaderItem(int column) const:
-
[virtual] QModelIndex QStandardItemModel::index(int row, int column, const QModelIndex &parent = QModelIndex()) const:
-
QModelIndex QStandardItemModel::indexFromItem(const QStandardItem *item) const:
-
void QStandardItemModel::insertColumn(int column, const QList<QStandardItem *> &items):
-
bool QStandardItemModel::insertColumn(int column, const QModelIndex &parent = QModelIndex()):
-
[virtual] bool QStandardItemModel::insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()):从QAbstractItemModel :: insertColumns()函数中重新实现。
-
void QStandardItemModel::insertRow(int row, const QList<QStandardItem *> &items):
-
void QStandardItemModel::insertRow(int row, QStandardItem *item):
-
bool QStandardItemModel::insertRow(int row, const QModelIndex &parent = QModelIndex()):
-
[virtual] bool QStandardItemModel::insertRows(int row, int count, const QModelIndex &parent = QModelIndex()):
-
QStandardItem *QStandardItemModel::invisibleRootItem() const:
-
QStandardItem *QStandardItemModel::item(int row, int column = 0) const:
-
[signal] void QStandardItemModel :: itemChanged(QStandardItem *item):
-
[virtual] QMap<int,QVariant> QStandardItemModel :: itemData(const QModelIndex &index) const:
-
QStandardItem *QStandardItemModel::itemFromIndex(const QModelIndex &index) const:
-
const QStandardItem *QStandardItemModel::itemPrototype() const:
-
[virtual] QMimeData *QStandardItemModel :: mimeData(const QModelIndexList &indexes) const:
-
[virtual] QStringList QStandardItemModel :: mimeTypes() const:
-
[virtual] QModelIndex QStandardItemModel::parent(const QModelIndex &child) const:
-
[virtual] bool QStandardItemModel::removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()):
-
[virtual] bool QStandardItemModel::removeRows(int row, int count, const QModelIndex &parent = QModelIndex()):
-
[virtual] int QStandardItemModel::rowCount(const QModelIndex &parent = QModelIndex()) const:
-
void QStandardItemModel::setColumnCount(int columns):
-
[virtual] bool QStandardItemModel::setData(const QModelIndex &index,const QVariant &value,int role = Qt :: EditRole):
-
[virtual] bool QStandardItemModel::setHeaderData(int section,Qt :: Orientation orientation,const QVariant &value,int role = Qt :: EditRole):
-
void QStandardItemModel::setHorizontalHeaderItem(int column,QStandardItem *item):
-
void QStandardItemModel::setHorizontalHeaderLabels(const QStringList &labels):
-
void QStandardItemModel::setItem(int row,int column,QStandardItem *item):
-
void QStandardItemModel::setItem(int row,QStandardItem *item):
-
[virtual] bool QStandardItemModel::setItemData(const QModelIndex &index,const QMap <int,QVariant> &roles):
-
void QStandardItemModel::setItemPrototype(const QStandardItem *item):
-
void QStandardItemModel::setItemRoleNames(const QHash<int,QByteArray> &roleNames):
-
void QStandardItemModel::setRowCount(int rows):
-
void QStandardItemModel::setVerticalHeaderItem(int row,QStandardItem *item):
-
void QStandardItemModel::setVerticalHeaderLabels(const QStringList &labels):
-
[virtual] QModelIndex QStandardItemModel::sibling(int row,int column,const QModelIndex &idx) const:
-
[virtual] void QStandardItemModel::sort(int column,Qt :: SortOrder order = Qt :: AscendingOrder):
-
[virtual] Qt :: DropActions QStandardItemModel :: supportedDropActions() const:
-
QList<QStandardItem *> QStandardItemModel::takeColumn(int column):
-
QStandardItem *QStandardItemModel::takeHorizontalHeaderItem(int column):
-
QStandardItem *QStandardItemModel::takeItem(int row,int column = 0):
-
QList<QStandardItem *> QStandardItemModel::takeRow(int row):
-
QStandardItem *QStandardItemModel::takeVerticalHeaderItem(int row):
-
QStandardItem *QStandardItemModel :: verticalHeaderItem(int row) const:
3 QStandardItemModel的使用
-
打开一个纯文本文件,该文件是规则的二维数据文件,通过字符串处理获取表头和各行各 列的数据,导入到一个QStandardItemModel数据模型。
-
编辑修改数据模型的数据,可以插入行、添加行、删除行,还可以在QTableView视图组 件中直接修改单元格的数据内容。
-
可以设置数据模型中某个项的不同角色的数据,包括文字对齐方式、字体是否粗体等。
-
通过QItemSelectionModel获取视图组件上的当前单元格,以及选择单元格的范围,对选 择的单元格进行操作。
-
将数据模型的数据内容显示到QPlainTextEdit组件里,显示数据模型的内容,检验视图组 件上做的修改是否与数据模型同步。
-
将修改后的模型数据另存为一个文本文件。
3.1 界面设计与主窗口类定义
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
//用于状态栏的信息显示
QLabel *LabCurFile; //当前文件
QLabel *LabCellPos; //当前单元格行列号
QLabel *LabCellText; //当前单元格内容
QStandardItemModel *theModel;//数据模型
QItemSelectionModel *theSelection;//Item选择模型
void iniModelFromStringList(QStringList&);//从StringList初始化数据模型
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
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_actModelData_triggered(); //导出模型数据
void on_actSave_triggered();//保存文件
void on_actAlignCenter_triggered();//居中对齐
void on_actFontBold_triggered(bool checked);//粗体字体
void on_actAlignLeft_triggered(); //居左对齐
void on_actAlignRight_triggered();//居右对齐
private:
Ui::MainWindow *ui;
};
这里定义了数据模型变量theModel,项数据选择模型变量theSelection。
定义的私有函数iniModelFromStringList()用于在打开文件时,从一个QStringList变量的内容创建数据模型。
自定义槽函数oncurrentChanged()用于在TableView上选择单元格发生变化时,更新状态栏的信息显示,这个槽函数将会与项选择模型theSelection的currentChanged()信号关联。
3.2 系统初始化
在MainWindow的构造函数中进行界面初始化,数据模型和选择模型的创建,以及与视图组
件的关联,信号与槽的关联等设置,代码如下:
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);
//创建状态栏组件
...
}
在构造函数里首先创建数据模型theModel,创建数据选择模型时需要传递一个数据模型变量
作为其参数。这样,数据选择模型theSelection就与数据模型theModeI关联,用于表示theModel
的项数据选择操作。
创建数据模型和选择模型后,为TableView组件设置数据模型和选择模型:
theModel = new QStandardItemModel(2,FixedColumnCount,this); //数据模型
theSelection = new QItemSelectionModel(theModel);//Item选择模型
构造函数里还将自定义的槽函数oncurrentChanged()与theSelection的currentChanged()信号关
联,用于界面上tableView选择单元格发生变化时,显示单元格的行号、列号、内容等信息,槽函
数代码如下:
void MainWindow::on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
{ //选择单元格变化时的响应
if (current.isValid()) //当前模型索引有效
{
LabCellPos->setText(QString::asprintf("当前单元格:%d行,%d列",
current.row(),current.column())); //显示模型索引的行和列号
QStandardItem *aItem;
aItem=theModel->itemFromIndex(current); //从模型索引获得Item
this->LabCellText->setText("单元格内容:"+aItem->text()); //显示item的文字内容
QFont font=aItem->font(); //获取item的字体
ui->actFontBold->setChecked(font.bold()); //更新actFontBold的check状态
}
}
3.3 从文本文件导入数据
QStandardItemModel是标准的基于项数据的数据模型,以类似于二维数组的形式管理内部数据,适合于处理表格型数据,其显示一般采用QTableView。
QStandardItemModel的数据可以是程序生成的内存中的数据,也可以来源于文件。例如,在实际数据处理中,有些数据经常是以纯文本格式保存的,它们有固定的列数,每一列是一项数据,实际构成一个二维数据表。图1是本实例程序要打开的一个纯文本文件的内容,文件的第1行
是数据列的文字标题,相当于数据表的表头,然后以行存储数据,以TAB键间隔每列数据。
当单击工具栏上的“打开文件”按钮时,需要选择一个这样的文件导入到数据模型,并在tableView上进行显示和编辑。图1的数据有6列,第1列是整数,第2至4列是浮点数,第5列是文字,第6列是逻辑型变量,“1”表示true。
图1 纯文本格式的数据文件
下面是“打开文件”按钮的槽函数代码:
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); //用文本流读取文件
ui->plainTextEdit->clear();//清空
while (!aStream.atEnd())
{
QString str=aStream.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);
iniModelFromStringList(fFileContent);//从StringList的内容初始化数据模型
}
}
3.4 数据修改
-
添加行
void MainWindow::on_actAppend_triggered()
{ //在表格最后添加行
QList<QStandardItem*> aItemList; //容器类
QStandardItem *aItem; //数据管理的基本单元
for(int i=0;i<FixedColumnCount-1;i++) //不包含最后1列
{
aItem=new QStandardItem("0"); //创建Item
aItemList<<aItem; //添加到容器
}
//获取最后一列的表头文字
QString str=theModel->headerData(theModel->columnCount()-1,Qt::Horizontal,Qt::DisplayRole).toString();
aItem=new QStandardItem(str); //创建 "测井取样"Item
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);//设置刚插入的行为当前选择行
}
-
插入行
void MainWindow::on_actInsert_triggered()
{//插入行
QList<QStandardItem*> aItemList; //QStandardItem的列表类
QStandardItem *aItem;
for(int i=0;i<FixedColumnCount-1;i++)
{
aItem=new QStandardItem("0"); //新建一个QStandardItem
aItemList<<aItem;//添加到列表类
}
QString str; //获取表头文字
str=theModel->headerData(theModel->columnCount()-1,Qt::Horizontal,Qt::DisplayRole).toString();
aItem=new QStandardItem(str); //创建Item
aItem->setCheckable(true);//设置为可使用CheckBox
aItemList<<aItem;//添加到列表类
QModelIndex curIndex=theSelection->currentIndex(); //获取当前选中项的模型索引
theModel->insertRow(curIndex.row(),aItemList); //在当前行的前面插入一行
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);
}
}
3.5 单元格格式设置
void MainWindow::on_actAlignCenter_triggered()
{//文字居中对齐
if (!theSelection->hasSelection())
return;
QModelIndexList selectedIndex=theSelection->selectedIndexes()
QModelIndex aIndex;
QStandardItem *aItem;
for (int i=0;i<selectedIndex.count();i++)
{
aIndex=selectedIndex.at(i);
aItem=theModel->itemFromIndex(aIndex);
aItem->setTextAlignment(Qt::AlignHCenter);
}
}
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); //重新设置字体
}
}
3.6 数据另存为文件
在视图组件上对数据的修改都会自动更新到数据模型里,单击工具栏上的“模型数据预览”按钮,可以将数据模型的数据内容显示到PlainTextEdit里。
数据模型里的数据是在内存中的,工具栏上的“另存文件”按钮可以将数据模型的数据另存为一个数据文本文件,同时也显示在PlainTextEdit里,其实现代码如下:
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";
}
}