本文主要研究了一下如何把树形结构的数据保存到文件并读取出来。为了更形象说明用了一个界面程序显示,程序用了model/view框架。
数据类
DataItem 就是保存在树形结构的基本数据。其最重要的保存数据的函数是SerialzeData
- class DataItem
- {
- public:
-
- DataItem(int id = 100,QString name = "root");
- ~DataItem();
-
- void SetRoot(DataItem *root);
- void SerialzeData(bool isSave,QDataStream &stream);
- void Clear();
- void Init();
-
- int GetID()
- {
- return ID;
- }
-
- QString GetName()
- {
- return Name;
- }
-
- void SetID(int id)
- {
- ID = id;
- }
-
- void SetName(QString name)
- {
- Name = name;
- }
-
- int GetSize()
- {
- return dataVec.size();
- }
-
- void AddItem(DataItem *pItem);
-
- void DeleteItem(DataItem *pItem);
-
- void DeleteItem(int index);
-
- DataItem *GetItem(int index);
-
- DataItem *GetParent()
- {
- return pRoot;
- }
-
- int indexOf(DataItem* pItem);
- private:
- int ID;
- QString Name;
- vector<DataItem*> dataVec;
- DataItem *pRoot;
- };
数据模型
TreeDataModel的底层数据就是上面定义的DataItem。用这种视图/模型的编程方式可以尽量减少数据与界面的耦合性。由于继承了QAbstractItemModel。所以必须重写其中的五个纯虚函数columnCount (),data(),index (),parent ()和rowCount()。
- class TreeDataModel:public QAbstractItemModel
- {
- Q_OBJECT
- public:
- TreeDataModel(QObject *parent = NULL);
- ~TreeDataModel();
-
- void SetRoot(DataItem *pRoot)
- {
- m_pTreeData = pRoot;
- }
- QModelIndex parent ( const QModelIndex & index ) const;
- QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const ;
- QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
- QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const;
- int columnCount ( const QModelIndex & parent = QModelIndex() ) const;
- int rowCount ( const QModelIndex & parent = QModelIndex() ) const;
- DataItem* dataFromIndex(const QModelIndex &index) const;
-
- void SaveData(QDataStream &out);
- void LoadData(QDataStream &in);
- protected:
- private:
- DataItem *m_pTreeData;
- };
- TreeDataModel::TreeDataModel( QObject *parent
- {
- m_pTreeData = NULL;
- }
-
- TreeDataModel::~TreeDataModel()
- {
-
- }
-
- QVariant TreeDataModel::data( const QModelIndex & index, int role
- {
- DataItem *pItem = dataFromIndex(index);
- if ((pItem)&&(role == Qt::DisplayRole))
- {
- switch (index.column())
- {
- case 0:
- return pItem->GetID();
- case 1:
- return pItem->GetName();
- }
- }
- return QVariant();
-
- }
-
- QVariant TreeDataModel::headerData( int section, Qt::Orientation orientation, int role
- {
- if ((section <2) && (orientation == Qt::Horizontal)&& (role == Qt::DisplayRole))
- {
- switch (section)
- {
- case 0:
- return tr("编号");
-
- case 1:
- return tr("名称");
- default:
- return QVariant();
- }
- }
- else
- {
- return QVariant();
- }
- }
-
- QModelIndex TreeDataModel::index( int row, int column, const QModelIndex & parent
- {
- if (!m_pTreeData ||row < 0 || column < 0)
- {
- return QModelIndex();
- }
- else
- {
- DataItem *pItem = dataFromIndex(parent);
- if (pItem)
- {
- DataItem *pChild = pItem->GetItem(row);
- if (pChild)
- {
- return createIndex(row,column,pChild);
- }
- }
- return QModelIndex();
- }
- }
-
- int TreeDataModel::columnCount( const QModelIndex & parent
- {
- return 2;
- }
-
- int TreeDataModel::rowCount( const QModelIndex & parent
- {
- DataItem *pItem = dataFromIndex(parent);
- if (pItem)
- {
- return pItem->GetSize();
- }
- return 0;
- }
-
- DataItem* TreeDataModel::dataFromIndex( const QModelIndex &index ) const
- {
- if (index.isValid())
- {
- return static_cast<DataItem*>(index.internalPointer());
- }
- else
- {
- return m_pTreeData;
- }
- }
-
- QModelIndex TreeDataModel::parent( const QModelIndex & index ) const
- {
- if (index.isValid())
- {
- DataItem *pItem = dataFromIndex(index);
- if (pItem)
- {
- DataItem *pParent = pItem->GetParent();
- if (pParent)
- {
- DataItem *pGrandParent = pParent->GetParent();
- if (pGrandParent)
- {
- int row = pGrandParent->indexOf(pParent);
- return createIndex(row,index.column(),pParent);
- }
- }
- }
- }
- return QModelIndex();
- }
-
- void TreeDataModel::SaveData( QDataStream &out )
- {
- m_pTreeData->SerialzeData(true,out);
- }
-
- void TreeDataModel::LoadData( QDataStream &in )
- {
- m_pTreeData->SerialzeData(false,in);
- }
主框架类
这个类主要实现左边的树形把数据保存到文件中,然后在右边的树形结构加载显示出来。
- class MainWidget:public QWidget
- {
- Q_OBJECT
- public:
- MainWidget(QWidget *patent = NULL);
- ~MainWidget();
-
- protected slots:
- void leftSelectBtnSlot();
- void rightSelectBtnSlot();
- void saveBtnSlot();
- void loadBtnSlot();
-
- private:
- QSplitter *m_pSplitter;
- QTreeView *m_pLeftTreeView;
- QTreeView *m_pRightTreeView;
- QPushButton *m_pLeftSaveBtn;
- QPushButton *m_pRightLoadBtn;
- QPushButton *m_pLeftSelectBtn;
- QPushButton *m_pRightSelectBtn;
- QLineEdit *m_pLeftLEdit;
- QLineEdit *m_pRightLEdit;
- QGridLayout *m_pLeftLayout;
- QGridLayout *m_pRightLayout;
-
- TreeDataModel *m_pLeftModel;
- TreeDataModel *m_pRightModel;
-
-
- };
- MainWidget::MainWidget( QWidget *patent
- {
- m_pLeftModel = new TreeDataModel();
- m_pRightModel = new TreeDataModel();
-
- m_pSplitter = new QSplitter(this);
- QFrame *pLeftFrame = new QFrame(this);
- QFrame *pRightFrame = new QFrame(this);
- m_pLeftLayout = new QGridLayout(pLeftFrame);
- m_pRightLayout = new QGridLayout(pRightFrame);
- m_pLeftLEdit = new QLineEdit(this);
- m_pRightLEdit = new QLineEdit(this);
- m_pLeftSaveBtn = new QPushButton(tr("保存"),this);
- m_pRightLoadBtn = new QPushButton(tr("加载"),this);
- m_pLeftTreeView = new QTreeView(this);
- m_pRightTreeView = new QTreeView(this);
- m_pLeftSelectBtn = new QPushButton(tr("选择文件"),this);
- m_pRightSelectBtn = new QPushButton(tr("选择文件"),this);
- m_pRightLEdit->setReadOnly(true);
-
-
- m_pLeftLayout->addWidget(m_pLeftSelectBtn,0,0,1,1);
- m_pLeftLayout->addWidget(m_pLeftLEdit,0,1,1,1);
- m_pLeftLayout->addWidget(m_pLeftSaveBtn,0,2,1,1);
- m_pLeftLayout->addWidget(m_pLeftTreeView,1,0,3,3);
-
- m_pRightLayout->addWidget(m_pRightSelectBtn,0,0,1,1);
- m_pRightLayout->addWidget(m_pRightLEdit,0,1,1,1);
- m_pRightLayout->addWidget(m_pRightLoadBtn,0,2,1,1);
- m_pRightLayout->addWidget(m_pRightTreeView,1,0,3,3);
-
- m_pLeftTreeView->setModel(m_pLeftModel);
- m_pRightTreeView->setModel(m_pRightModel);
- DataItem *pTreeData = new DataItem();
- pTreeData->SetRoot(pTreeData);
- pTreeData->Init();
-
- m_pLeftModel->SetRoot(pTreeData);
-
-
- m_pSplitter->addWidget(pLeftFrame);
- m_pSplitter->addWidget(pRightFrame);
-
- connect(m_pLeftSelectBtn,SIGNAL(clicked()),this,SLOT(leftSelectBtnSlot()));
- connect(m_pRightSelectBtn,SIGNAL(clicked()),this,SLOT(rightSelectBtnSlot()));
- connect(m_pLeftSaveBtn,SIGNAL(clicked()),this,SLOT(saveBtnSlot()));
- connect(m_pRightLoadBtn,SIGNAL(clicked()),this,SLOT(loadBtnSlot()));
- this->setFixedSize(QSize(650,250));
- }
-
- MainWidget::~MainWidget()
- {
-
- }
-
- void MainWidget::leftSelectBtnSlot()
- {
- QFileDialog Dialog(this,tr("选择目录"),"","");
- Dialog.setFileMode(QFileDialog::Directory);
-
- if (Dialog.exec())
- {
- QStringList dirs = Dialog.selectedFiles();
- if (dirs.size() > 0)
- {
- m_pLeftLEdit->setText(QDir::toNativeSeparators(dirs.at(0)));
- }
- }
- }
-
- void MainWidget::rightSelectBtnSlot()
- {
- QFileDialog Dialog(this,tr("选择文件"),"","");
- Dialog.setFileMode(QFileDialog::ExistingFile);
- Dialog.setNameFilter("*.data");
- if (Dialog.exec())
- {
- QStringList files = Dialog.selectedFiles();
- if (files.size() > 0)
- {
- m_pRightLEdit->setText(QDir::toNativeSeparators(files.at(0)));
- }
- }
- }
-
- void MainWidget::saveBtnSlot()
- {
- QString filePath = m_pLeftLEdit->text();
- if ((filePath.isEmpty()) || filePath.endsWith("\\") || filePath.endsWith("/"))
- {
- QMessageBox::information(this,tr("提示"),tr("请输入文件名"),QMessageBox::Ok);
- return;
- }
- else if(filePath.endsWith("data"))
- {
- QFile file(filePath);
- if (file.open(QIODevice::WriteOnly))
- {
- QDataStream outStream(&file);
- m_pLeftModel->SaveData(outStream);
- }
- }
- }
-
- void MainWidget::loadBtnSlot()
- {
- QString filePath = m_pRightLEdit->text();
- if((!filePath.isEmpty()) &&filePath.endsWith("data"))
- {
- DataItem *pTreeData = new DataItem();
-
- m_pRightModel->SetRoot(pTreeData);
-
- QFile file(filePath);
- if (file.open(QIODevice::ReadOnly))
- {
- QDataStream inStream(&file);
- m_pRightModel->LoadData(inStream);
- m_pRightTreeView->setModel(m_pRightModel);
- m_pRightTreeView->reset();
- }
- }
- }
运行结果如下图

http://blog.csdn.net/hai200501019/article/details/11022581
文件保存树形结构数据
原文:http://www.cnblogs.com/findumars/p/5176052.html