zoukankan      html  css  js  c++  java
  • qt mvc3

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

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

    数据存放的格式

    学号 姓名 性别

    xxx xxx x

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

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

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

    下面代码贴出来

    Student


    #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

    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\


    #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是一个模板类

    [cpp] view plaincopyprint?
    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

    #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

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


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

    [cpp] view plaincopyprint?


    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

    #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

    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

    #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!");
    }
    }

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


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

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

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

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

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

    无图无真相




  • 相关阅读:
    Oracle数据类型
    Windows10安装node.js,vue.js以及创建第一个vue.js项目
    Redis Desktop Manager安装
    VMware安装Linux系统
    前端入门学习路线
    架构
    HTML
    Oracle修改表类型方法
    Python学习
    Python(字符串和编码)
  • 原文地址:https://www.cnblogs.com/lvdongjie/p/3736215.html
Copyright © 2011-2022 走看看