Qt mvc 三

來源:互聯網
上載者:User

前面兩節講的model是一維的,這次開始二維的也就是我們常說的Table,相對與list,我們多了一個列的概念。

下面講解一個例子。我先說明一下我們這個例子,在程式目錄下,我們有一個文字檔,其中存放的學生資訊。

資料存放的格式

學號       姓名       性別

xxx         xxx           x

每個學生的資訊佔一行,現在我們需要將這個檔案中的所有學生資訊載入顯示。

在例子中主要涉及這幾個類,Student,FileReader和DataTableModel類。

Student是學生實體類,FileRead從檔案載入資料,後面的一個就是我們的model了。

下面代碼貼出來

Student

/**************************************************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){}inlineconst QString& Student::getNo() const{    return m_no;}inlineconst QString& Student::getName() const{    return m_name;}inlineconst 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 QDataStreamtemplate <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>inlineFileReader<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,其中我使用了我的蹩腳的英文寫了注釋

/**************************************************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 knowtypedef Student T;class DataTableModel : public QAbstractTableModel{    Q_OBJECTpublic:    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!");    }}

本來是想也做成模板的,可是Qt元對象系統和模板機制是存在衝突的,以後講為什麼衝突。這裡我使用了typedef來提前做了編譯器應該做的事避免了衝突

data,rowCounts,flag,headerData這些都是需要重新實現的,在二維中columnCount就需要重新實現了。

只是為了顯示所以flag很簡單。

大家也看見了我在Student中實現的members,describe的用處,和重載[]所帶來的便捷。

我們的列數就是需要對外實現的成員數,describe就是得到成員的描述。其實我感覺已經有點架構的味道了...算了不說大話了

其中的一個bug我已經用英文說了。

無圖無真相

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.