Qt mvc 三

来源:互联网 发布:自然堂 淘宝销售额 编辑:程序博客网 时间:2024/05/22 00:50

前面两节讲的model是一维的,这次开始二维的也就是我们常说的Table,相对与list,我们多了一个列的概念。

下面讲解一个例子。我先说明一下我们这个例子,在程序目录下,我们有一个文本文件,其中存放的学生信息。

数据存放的格式

学号       姓名       性别

xxx         xxx           x

每个学生的信息占一行,现在我们需要将这个文件中的所有学生信息加载显示。

在例子中主要涉及这几个类,Student,FileReader和DataTableModel类。

Student是学生实体类,FileRead从文件加载数据,后面的一个就是我们的model了。

下面代码贴出来

Student

[cpp] view plaincopyprint?
  1. /************************************************ 
  2. * 
  3. *author:周翔 
  4. *e-mail:604487178@qq.com 
  5. *blog:http://blog.csdn.net/zhx6044 
  6. * 
  7. * 
  8. *************************************************/  
  9.   
  10. #ifndef STUDENT_HPP  
  11. #define STUDENT_HPP  
  12. #include <QString>  
  13. #include <QTextStream>  
  14.   
  15. class Student  
  16. {  
  17.     friend QTextStream& operator >>(QTextStream &in,Student &t) {  
  18.         in >> t.m_no >> t.m_name >> t.m_sex;  
  19.         return in;  
  20.     }  
  21.   
  22. public:  
  23.     Student(){}  
  24.     Student(const QString &no, const QString &name,const QString &sex);  
  25.     const QString& getNo() const;  
  26.     const QString& getName() const;  
  27.     const QString& getSex() const;  
  28.   
  29.     static int members() {  
  30.         return 3;  
  31.     }  
  32.   
  33.     QString operator [](int i) const{  
  34.   
  35.         switch (i) {  
  36.         case 0:  
  37.             return m_no;  
  38.         case 1:  
  39.             return m_name;  
  40.         case 2:  
  41.             return m_sex;  
  42.         default:  
  43.             break;  
  44.         }  
  45.         return QString();  
  46.     }  
  47.   
  48.     static QString describe(int i) {  
  49.         switch (i) {  
  50.         case 0:  
  51.             return "No.";  
  52.         case 1:  
  53.             return "Name";  
  54.         case 2:  
  55.             return "Sex";  
  56.         default:  
  57.             break;  
  58.         }  
  59.         return QString();  
  60.     }  
  61.   
  62. private:  
  63.     QString m_no;  
  64.     QString m_name;  
  65.     QString m_sex;  
  66.   
  67. };  
  68.   
  69. #endif // STUDENT_HPP  
  70.   
  71. /************************************************ 
  72. * 
  73. *author:周翔 
  74. *e-mail:604487178@qq.com 
  75. *blog:http://blog.csdn.net/zhx6044 
  76. * 
  77. * 
  78. *************************************************/  
  79.   
  80. #include "student.hpp"  
  81.   
  82. Student::Student(const QString &no, const QString &name, const QString &sex):  
  83.     m_no(no),  
  84.     m_name(name),  
  85.     m_sex(sex)  
  86. {  
  87. }  
  88.   
  89. inline  
  90. const QString& Student::getNo() const  
  91. {  
  92.     return m_no;  
  93. }  
  94.   
  95. inline  
  96. const QString& Student::getName() const  
  97. {  
  98.     return m_name;  
  99. }  
  100.   
  101. inline  
  102. const QString& Student::getSex() const  
  103. {  
  104.     return m_sex;  
  105. }  
Student类有三个数据成员,m_no学号,m_name姓名,m_sex性别。两个静态成员函数对类属性的一些描述,这个是侵入性的,后面优化可以是非侵入式的。

重载的[]是为了使用方便,>>是为了支持流。

FileReader是一个模板类

[cpp] view plaincopyprint?
  1. /************************************************ 
  2. * 
  3. *author:周翔 
  4. *e-mail:604487178@qq.com 
  5. *blog:http://blog.csdn.net/zhx6044 
  6. * 
  7. * 
  8. *************************************************/  
  9.   
  10. #ifndef FILEREADER_HPP  
  11. #define FILEREADER_HPP  
  12. #include <QFile>  
  13. #include <QTextStream>  
  14.   
  15.   
  16. #include "student.hpp"  
  17.   
  18. //you also can use QDataStream  
  19.   
  20. template <typename T>  
  21. class FileReader  
  22. {  
  23. public:  
  24.     FileReader(const QString &name);  
  25.     ~FileReader();  
  26.     bool open();  
  27.     bool hasNext();  
  28.     T getNext();  
  29. private:  
  30.     QString m_fileName;  
  31.     QFile m_file;  
  32.     QTextStream m_stream;  
  33.   
  34. };  
  35.   
  36.   
  37. template <typename T>  
  38. inline  
  39. FileReader<T>::FileReader(const QString &name):m_fileName(name)  
  40. {  
  41.   
  42. }  
  43.   
  44. template <typename T>  
  45. FileReader<T>::~FileReader()  
  46. {  
  47.     if (m_file.isOpen()) {  
  48.         m_file.close();  
  49.     }  
  50. }  
  51.   
  52. template <typename T>  
  53. bool FileReader<T>::open()  
  54. {  
  55.     m_file.setFileName(m_fileName);  
  56.     if (m_file.open(QIODevice::ReadWrite)) {  
  57.         m_stream.setDevice(&m_file);  
  58.         return true;  
  59.     }  
  60.     return false;  
  61. }  
  62. template <typename T>  
  63. bool FileReader<T>::hasNext()  
  64. {  
  65.     if (m_file.isOpen()) {  
  66.   
  67.         return !m_stream.atEnd();  
  68.     }  
  69.     return false;  
  70. }  
  71.   
  72. template <typename T>  
  73. T FileReader<T>::getNext()  
  74. {  
  75.     T t;  
  76.     m_stream >> t;  
  77.     return t;  
  78. }  
  79.   
  80.   
  81.   
  82. #endif // FILEREADER_HPP  

构造参数是加载数据的文件名,提供了open操作,hasNext是判断是否结束,getNext得到一个加载的对象。

下面是我们的models,其中我使用了我的蹩脚的英文写了注释

[cpp] view plaincopyprint?
  1. /************************************************ 
  2. * 
  3. *author:周翔 
  4. *e-mail:604487178@qq.com 
  5. *blog:http://blog.csdn.net/zhx6044 
  6. * 
  7. * 
  8. *************************************************/  
  9.   
  10. #ifndef DATATABLEMODEL_HPP  
  11. #define DATATABLEMODEL_HPP  
  12.   
  13. #include <QAbstractTableModel>  
  14. #include <vector>  
  15.   
  16.   
  17. #include "student.hpp"  
  18. #include "filereader.hpp"  
  19.   
  20. //Here,I want to use 'template class',but  is not supported by the macor 'Q_OBJECT',  
  21. //so I use typedef,of cause you also use macor  
  22. //If you want to use it,the type of T use should  implement the two static function  
  23. //and overload operator[] and >>--int members(),it return T numbers of members,  
  24. //QString describe(int ),the describe about T.operator[](int i),return the i-st member data.  
  25. //the >> you know  
  26. typedef Student T;  
  27.   
  28. class DataTableModel : public QAbstractTableModel  
  29. {  
  30.     Q_OBJECT  
  31. public:  
  32.     explicit DataTableModel(const QString &fileName,QObject *parent = 0);  
  33.   
  34.     int rowCount(const QModelIndex &parent) const;  
  35.     int columnCount(const QModelIndex &parent) const;  
  36.     Qt::ItemFlags flags(const QModelIndex &index) const;  
  37.     QVariant data(const QModelIndex &index, int role) const;  
  38.     QVariant headerData(int section, Qt::Orientation orientation, int role) const;  
  39. signals:  
  40.     void sig_error(const QString &info);  
  41. public slots:  
  42. private:  
  43.     QString m_fileName;  
  44.     //use vector,loading data form file may low speed,but seaching is fast!  
  45.     std::vector<T> m_data;  
  46.   
  47.     void load();  
  48. };  
  49.   
  50.   
  51.   
  52. #endif // DATATABLEMODEL_HPP  
  53.   
  54. /************************************************ 
  55. * 
  56. *author:周翔 
  57. *e-mail:604487178@qq.com 
  58. *blog:http://blog.csdn.net/zhx6044 
  59. * 
  60. * 
  61. *************************************************/  
  62. #include "datatablemodel.hpp"  
  63.   
  64.   
  65. DataTableModel::DataTableModel(const QString &fileName, QObject *parent):  
  66.     QAbstractTableModel(parent),  
  67.     m_fileName(fileName)  
  68. {  
  69.     load();  
  70. }  
  71.   
  72. int DataTableModel::rowCount(const QModelIndex &/*parent*/const  
  73. {  
  74.     return m_data.size();  
  75. }  
  76.   
  77. int DataTableModel::columnCount(const QModelIndex &/*parent*/const  
  78. {  
  79.     return T::members();  
  80. }  
  81.   
  82.   
  83. Qt::ItemFlags DataTableModel::flags(const QModelIndex &/*index*/const  
  84. {  
  85.     return Qt::ItemIsEnabled;  
  86. }  
  87.   
  88.   
  89. QVariant DataTableModel::data(const QModelIndex &index, int role) const  
  90. {  
  91.     if (index.isValid() && role == Qt::DisplayRole) {  
  92.         return m_data[index.row()][index.column()];  
  93.     }  
  94.     return QVariant();  
  95. }  
  96.   
  97.   
  98. QVariant DataTableModel::headerData(int section, Qt::Orientation orientation, int role) const  
  99. {  
  100.     if (role != Qt::DisplayRole) {  
  101.         return QVariant();  
  102.     }  
  103.     if (orientation == Qt::Vertical) {  
  104.         return QString("row %1").arg(section);  
  105.     } else {  
  106.         return T::describe(section);  
  107.     }  
  108.     return QVariant();  
  109. }  
  110. /** 
  111.  * @brief DataTableModel::load load data from file 
  112.  */  
  113. void DataTableModel::load()  
  114. {  
  115.     //create a file reader that can read object about type of T from file  
  116.     //which name is m_fileName,the type of T should overload the operator >> on QTextStream.  
  117.     //A bug about FileReader,the last read is empty because the file is end with empty line.  
  118.     //But I think it is not a problem.  
  119.     FileReader<T> fr(m_fileName);  
  120.     if (fr.open()) {  
  121.         while (fr.hasNext()) {  
  122.             m_data.push_back(fr.getNext());  
  123.         }  
  124.     } else {  
  125.         emit sig_error("load data failure!");  
  126.     }  
  127. }  

本来是想也做成模板的,可是Qt元对象系统和模板机制是存在冲突的,以后讲为什么冲突。这里我使用了typedef来提前做了编译器应该做的事避免了冲突

data,rowCounts,flag,headerData这些都是需要重新实现的,在二维中columnCount就需要重新实现了。

只是为了显示所以flag很简单。

大家也看见了我在Student中实现的members,describe的用处,和重载[]所带来的便捷。

我们的列数就是需要对外实现的成员数,describe就是得到成员的描述。其实我感觉已经有点框架的味道了...尴尬算了不说大话了

其中的一个bug我已经用英文说了。

无图无真相

z

转自:

0 0
原创粉丝点击