前面两节讲的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我已经用英文说了。

无图无真相

qt mvc3的更多相关文章

  1. MVC3下的layout页面

    1.Layout页基础:如果你有使用MasterPage的经验,你将会记得如下的几个东西 A:<%@ Master %> B:<%@ Page %> C:<asp:Con ...

  2. QT内省机制、自定义Model、数据库

    本文将介绍自定义Model过程中数据库数据源的获取方法,我使用过以下三种方式获取数据库数据源: 创建 存储对应数据库所有字段的 结构体,将结构体置于容器中返回,然后根据索引值(QModelIndex) ...

  3. Ubuntu(Linux) + mono + xsp4 + nginx +asp.net MVC3 部署

    折腾了一下,尝试用Linux,部署mvc3. 分别用过 centos 和 ubuntu ,用ubuntu是比较容易部署的. 操作步骤如下: 一.终端分别如下操作 sudo su ->输入密码 a ...

  4. Ubuntu 下安装QT

    Ubuntu 下安装QT 本文使用的环境 QT Library: qt-everywhere-opensource-src-4.7.4.tar.gz QT Creator: qt-creator-li ...

  5. Qt安装配置

    Qt Creator: 下载: Qt 5.5.1 for Windows 32-bit(MinGW 4.9.2, 1.0 GB):http://download.qt.io/official_rele ...

  6. Qt信号与槽自动关联机制

    参考链接1:http://blog.csdn.net/skyhawk452/article/details/6121407 参考链接2:http://blog.csdn.net/memory_exce ...

  7. 保持Qt GUI响应的几种方法

    最开始使用Qt时就遇到过QT Gui失去响应的问题,我是用多线程的方式解决的,然而通常来说,多线程是会降低程序的运行速度. 之后,在使用QSqlQuery::execBatch()函数时,Qt Gui ...

  8. Qt 中使用Singleton模式需小心

    在qt中,使用Singleton模式时一定要小心.因为Singleton模式中使用的是静态对象,静态对象是直到程序结束才被释放的,然而,一旦把该静态对象纳入了Qt的父子对象体系,就会导致不明确的行为. ...

  9. Qt——组件位置随窗口变化

    当我们用Qt Designer设计界面时,有时会面临这样一个问题:需要在窗口指定位置放置组件,并且当窗口位置大小改变时,该组件相对其父对象的位置是不变的,如下面两幅图所示 ,首先看上面这幅图,注意bu ...

随机推荐

  1. k8s中的网络(较详细汇总)

    目录 一.网络前提条件-网络模型 二.需要解决的网络问题 1.容器和容器之间的网络 2.pod与pod之间的网络 同一台node节点上pod和pod通信 不同node节点上pod和pod通信 3.po ...

  2. 剖析.o文件ELF组成

    ELF文件结构组成 ①总共13个节 ②每个节都有一个编号.从ELF头开始编号,编号从0开始,编号的作用就是用来索引(找到)不同节的. ③每个.o的都是这样的结构.链接时要做的就是,将ELF格式的.o全 ...

  3. centos7 修改内核文件 网卡名称为标准名称eth0

    在开机安装系统之前按TAB键后输入标记信息后安装系统就可以变成标准网卡接口eth0 或eth1

  4. PAT基础级-钻石段位样卷2-7-5 福到了 (15 分)

    “福”字倒着贴,寓意“福到”.不论到底算不算民俗,本题且请你编写程序,把各种汉字倒过来输出.这里要处理的每个汉字是由一个 N × N 的网格组成的,网格中的元素或者为字符 @ 或者为空格.而倒过来的汉 ...

  5. Python3 acm基础输入输出

    案例一:输入字符串分割并转化成多个int数值 a, b= map(int, input().split()) try: while True: a, b= map(int, input().split ...

  6. 纯js验证码

    纯js验证码 <!DOCTYPE html> <html> <head> <title>纯js验证码</title> </head&g ...

  7. Kotlin重新学习及入门示例

    在2017和2018其实已经对Kotlin的基础语法进行了一些学习,但是!!如今已经是2019年,中间间断时间已经很长了,所以准备接下来从0再次出发深入系统完整的来审视一下该语言,毕境如今它的地位是越 ...

  8. Mybatis3.0-[tp_28-29]-映射文件-resultMap_自定义结果集映射规则_及关联环境的搭建

    笔记要点出错分析与总结工程组织 1.定义接口  EmployeeMapperPlus.java package com.dao; import com.bean.*; public interface ...

  9. MySQL进阶13--常见六大约束: 非空/默认/主键/唯一约束/检查约束/外键约束--表级约束 / 列级约束

    /* MySQL进阶13 常见六大约束: 1.not null 非空 2.default :默认值,用于保证该字段的默认值 ; 比如年龄:1900-10-10 3.primary key : 主键,用 ...

  10. Mysql DELETE 不能使用别名? 是我不会用!

    今天碰到一个sql问题,就是在delete中加了别名,导致报错了:"[Err] 1064 - You have an error in your SQL syntax; ..." ...