前面兩節講的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我已經用英文說了。
無圖無真相