前面两节讲的model是一维的,此次开始二维的也就是咱们常说的Table,相对与list,咱们多了一个列的概念。框架
下面讲解一个例子。我先说明一下咱们这个例子,在程序目录下,咱们有一个文本文件,其中存放的学生信息。函数
数据存放的格式优化
学号 姓名 性别.net
xxx xxx xcode
每一个学生的信息占一行,如今咱们须要将这个文件中的全部学生信息加载显示。orm
在例子中主要涉及这几个类,Student,FileReader和DataTableModel类。对象
Student是学生实体类,FileRead从文件加载数据,后面的一个就是咱们的model了。blog
下面代码贴出来ci
Studentget
/************************************************ * *author:周翔 *e-mail:604487178@qq.com *blog:http://blog.csdn.net/zhx6044 * * *************************************************/ #ifndef STUDENT_HPP #define STUDENT_HPP #include <QString> #include <QTextStream> class Student { friend QTextStream& operator >>(QTextStream &in,Student &t) { in >> t.m_no >> t.m_name >> t.m_sex; return in; } public: Student(){} Student(const QString &no, const QString &name,const QString &sex); const QString& getNo() const; const QString& getName() const; const QString& getSex() const; static int members() { return 3; } QString operator [](int i) const{ switch (i) { case 0: return m_no; case 1: return m_name; case 2: return m_sex; default: break; } return QString(); } static QString describe(int i) { switch (i) { case 0: return "No."; case 1: return "Name"; case 2: return "Sex"; default: break; } return QString(); } private: QString m_no; QString m_name; QString m_sex; }; #endif // STUDENT_HPP /************************************************ * *author:周翔 *e-mail:604487178@qq.com *blog:http://blog.csdn.net/zhx6044 * * *************************************************/ #include "student.hpp" Student::Student(const QString &no, const QString &name, const QString &sex): m_no(no), m_name(name), m_sex(sex) { } inline const QString& Student::getNo() const { return m_no; } inline const QString& Student::getName() const { return m_name; } inline const QString& Student::getSex() const { return m_sex; }Student类有三个数据成员,m_no学号,m_name姓名,m_sex性别。两个静态成员函数对类属性的一些描述,这个是侵入性的,后面优化能够是非侵入式的。
重载的[]是为了使用方便,>>是为了支持流。
FileReader是一个模板类
/************************************************ * *author:周翔 *e-mail:604487178@qq.com *blog:http://blog.csdn.net/zhx6044 * * *************************************************/ #ifndef FILEREADER_HPP #define FILEREADER_HPP #include <QFile> #include <QTextStream> #include "student.hpp" //you also can use QDataStream template <typename T> class FileReader { public: FileReader(const QString &name); ~FileReader(); bool open(); bool hasNext(); T getNext(); private: QString m_fileName; QFile m_file; QTextStream m_stream; }; template <typename T> inline FileReader<T>::FileReader(const QString &name):m_fileName(name) { } template <typename T> FileReader<T>::~FileReader() { if (m_file.isOpen()) { m_file.close(); } } template <typename T> bool FileReader<T>::open() { m_file.setFileName(m_fileName); if (m_file.open(QIODevice::ReadWrite)) { m_stream.setDevice(&m_file); return true; } return false; } template <typename T> bool FileReader<T>::hasNext() { if (m_file.isOpen()) { return !m_stream.atEnd(); } return false; } template <typename T> T FileReader<T>::getNext() { T t; m_stream >> t; return t; } #endif // FILEREADER_HPP
下面是咱们的models,其中我使用了个人蹩脚的英文写了注释
/************************************************ * *author:周翔 *e-mail:604487178@qq.com *blog:http://blog.csdn.net/zhx6044 * * *************************************************/ #ifndef DATATABLEMODEL_HPP #define DATATABLEMODEL_HPP #include <QAbstractTableModel> #include <vector> #include "student.hpp" #include "filereader.hpp" //Here,I want to use 'template class',but is not supported by the macor 'Q_OBJECT', //so I use typedef,of cause you also use macor //If you want to use it,the type of T use should implement the two static function //and overload operator[] and >>--int members(),it return T numbers of members, //QString describe(int ),the describe about T.operator[](int i),return the i-st member data. //the >> you know typedef Student T; class DataTableModel : public QAbstractTableModel { Q_OBJECT public: explicit DataTableModel(const QString &fileName,QObject *parent = 0); int rowCount(const QModelIndex &parent) const; int columnCount(const QModelIndex &parent) const; Qt::ItemFlags flags(const QModelIndex &index) const; QVariant data(const QModelIndex &index, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role) const; signals: void sig_error(const QString &info); public slots: private: QString m_fileName; //use vector,loading data form file may low speed,but seaching is fast! std::vector<T> m_data; void load(); }; #endif // DATATABLEMODEL_HPP /************************************************ * *author:周翔 *e-mail:604487178@qq.com *blog:http://blog.csdn.net/zhx6044 * * *************************************************/ #include "datatablemodel.hpp" DataTableModel::DataTableModel(const QString &fileName, QObject *parent): QAbstractTableModel(parent), m_fileName(fileName) { load(); } int DataTableModel::rowCount(const QModelIndex &/*parent*/) const { return m_data.size(); } int DataTableModel::columnCount(const QModelIndex &/*parent*/) const { return T::members(); } Qt::ItemFlags DataTableModel::flags(const QModelIndex &/*index*/) const { return Qt::ItemIsEnabled; } QVariant DataTableModel::data(const QModelIndex &index, int role) const { if (index.isValid() && role == Qt::DisplayRole) { return m_data[index.row()][index.column()]; } return QVariant(); } QVariant DataTableModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role != Qt::DisplayRole) { return QVariant(); } if (orientation == Qt::Vertical) { return QString("row %1").arg(section); } else { return T::describe(section); } return QVariant(); } /** * @brief DataTableModel::load load data from file */ void DataTableModel::load() { //create a file reader that can read object about type of T from file //which name is m_fileName,the type of T should overload the operator >> on QTextStream. //A bug about FileReader,the last read is empty because the file is end with empty line. //But I think it is not a problem. FileReader<T> fr(m_fileName); if (fr.open()) { while (fr.hasNext()) { m_data.push_back(fr.getNext()); } } else { emit sig_error("load data failure!"); } }
data,rowCounts,flag,headerData这些都是须要从新实现的,在二维中columnCount就须要从新实现了。
只是为了显示因此flag很简单。
你们也看见了我在Student中实现的members,describe的用处,和重载[]所带来的便捷。
咱们的列数就是须要对外实现的成员数,describe就是获得成员的描述。其实我感受已经有点框架的味道了...算了不说大话了
其中的一个bug我已经用英文说了。
无图无真相