Qt实现自定义模型基于QAbstractTableModel

两个例子

例子1代码

Main.cpp

#include <QtGui>

#include "currencymodel.h"

int main(int argc, char *argv[])
{
QApplication app(argc, argv); //数据源
QMap<QString, double> currencyMap;
currencyMap.insert("AUD", 1.3259);
currencyMap.insert("CHF", 1.2970);
currencyMap.insert("CZK", 24.510);
currencyMap.insert("DKK", 6.2168);
currencyMap.insert("EUR", 0.8333);
currencyMap.insert("GBP", 0.5661);
currencyMap.insert("HKD", 7.7562);
currencyMap.insert("JPY", 112.92);
currencyMap.insert("NOK", 6.5200);
currencyMap.insert("NZD", 1.4697);
currencyMap.insert("SEK", 7.8180);
currencyMap.insert("SGD", 1.6901);
currencyMap.insert("USD", 1.0000); //自定义表模型
CurrencyModel currencyModel;
currencyModel.setCurrencyMap(currencyMap);
//表视图
QTableView tableView;
//设置视图模型
tableView.setModel(&currencyModel);
//设置交替颜色
tableView.setAlternatingRowColors(true); tableView.setWindowTitle(QObject::tr("Currencies"));
tableView.show(); return app.exec();
}

currencymodel.h

#ifndef CURRENCYMODEL_H
#define CURRENCYMODEL_H #include <QAbstractTableModel>
#include <QMap> class CurrencyModel : public QAbstractTableModel
{
public:
CurrencyModel(QObject *parent = ); void setCurrencyMap(const QMap<QString, double> &map);
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation,
int role) const; private:
QString currencyAt(int offset) const; QMap<QString, double> currencyMap;
}; #endif

currencymodel.cpp

#include <QtCore>

#include "currencymodel.h"

CurrencyModel::CurrencyModel(QObject *parent)
: QAbstractTableModel(parent)
{
} void CurrencyModel::setCurrencyMap(const QMap<QString, double> &map)
{
currencyMap = map;
//重置模型至原始状态,告诉所有视图,他们数据都无效,强制刷新数据
reset();
} //返回行数
int CurrencyModel::rowCount(const QModelIndex & /* parent */) const
{
return currencyMap.count();
}
//返回列数
int CurrencyModel::columnCount(const QModelIndex & /* parent */) const
{
return currencyMap.count();
} //返回一个项的任意角色的值,这个项被指定为QModelIndex
QVariant CurrencyModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant(); if (role == Qt::TextAlignmentRole) {
return int(Qt::AlignRight | Qt::AlignVCenter);
} else if (role == Qt::DisplayRole) {
QString rowCurrency = currencyAt(index.row());
QString columnCurrency = currencyAt(index.column()); if (currencyMap.value(rowCurrency) == 0.0)
return "####"; double amount = currencyMap.value(columnCurrency)
/ currencyMap.value(rowCurrency); return QString("%1").arg(amount, , 'f', );
}
return QVariant();
}
//返回表头名称,(行号或列号,水平或垂直,角色)
QVariant CurrencyModel::headerData(int section,
Qt::Orientation /* orientation */,
int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
return currencyAt(section);
}
//获取当前关键字
QString CurrencyModel::currencyAt(int offset) const
{
return (currencyMap.begin() + offset).key();
}

例子2代码

Main.cpp

#include <QApplication>
#include <QHeaderView>
#include <QTableView> #include "citymodel.h" int main(int argc, char *argv[])
{
QApplication app(argc, argv); //保存城市名
QStringList cities;
cities << "Arvika" << "Boden" << "Eskilstuna" << "Falun"
<< "Filipstad" << "Halmstad" << "Helsingborg" << "Karlstad"
<< "Kiruna" << "Kramfors" << "Motala" << "Sandviken"
<< "Skara" << "Stockholm" << "Sundsvall" << "Trelleborg";
//模型
CityModel cityModel;
//
cityModel.setCities(cities); QTableView tableView;
tableView.setModel(&cityModel);
tableView.setAlternatingRowColors(true);
tableView.setWindowTitle(QObject::tr("Cities"));
tableView.show(); return app.exec();
}

citymodel.h

#ifndef CITYMODEL_H
#define CITYMODEL_H #include <QAbstractTableModel>
#include <QStringList>
#include <QVector> class CityModel : public QAbstractTableModel
{
Q_OBJECT public:
CityModel(QObject *parent = ); void setCities(const QStringList &cityNames);
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
bool setData(const QModelIndex &index, const QVariant &value,
int role);
QVariant headerData(int section, Qt::Orientation orientation,
int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const; private:
int offsetOf(int row, int column) const; QStringList cities;
QVector<int> distances;
}; #endif

citymodel.cpp

#include <QtCore>

#include "citymodel.h"

CityModel::CityModel(QObject *parent)
: QAbstractTableModel(parent)
{
}
//设定一下数据源
void CityModel::setCities(const QStringList &cityNames)
{
cities = cityNames;
//重新设置一下QVector distances的矩阵大小的,中间对角线为0不用存
distances.resize(cities.count() * (cities.count() - ) / );
//填充所有距离值为0
distances.fill();
//刷新所有视图数据
reset();
}
//模型行数
int CityModel::rowCount(const QModelIndex & /* parent */) const
{
return cities.count();
}
//模型列数
int CityModel::columnCount(const QModelIndex & /* parent */) const
{
return cities.count();
}
//赋值模型每个项的数据
QVariant CityModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant(); if (role == Qt::TextAlignmentRole) {
return int(Qt::AlignRight | Qt::AlignVCenter);
} else if (role == Qt::DisplayRole) {
if (index.row() == index.column())
return ;
int offset = offsetOf(index.row(), index.column());
return distances[offset];
}
return QVariant();
}
//编辑一个项
bool CityModel::setData(const QModelIndex &index,
const QVariant &value, int role)
{
if (index.isValid() && index.row() != index.column()
&& role == Qt::EditRole) {
int offset = offsetOf(index.row(), index.column());
distances[offset] = value.toInt();
//交换对应项的模型索引
QModelIndex transposedIndex = createIndex(index.column(),
index.row());
//某项发生改变,发射信号( between topLeft and bottomRight inclusive)
emit dataChanged(index, index);
emit dataChanged(transposedIndex, transposedIndex);
return true;
}
return false;
} //返回列表头
QVariant CityModel::headerData(int section,
Qt::Orientation /* orientation */,
int role) const
{
//返回在Cities字符串列表中给定偏移量的城市名称
if (role == Qt::DisplayRole)
return cities[section];
return QVariant();
}
//返回对一个项相关的操作的标识符(例如,是否可以编辑或者是否已选中等)
Qt::ItemFlags CityModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags flags = QAbstractItemModel::flags(index);
if (index.row() != index.column())
flags |= Qt::ItemIsEditable;
return flags;
}
//计算偏移量
int CityModel::offsetOf(int row, int column) const
{
if (row < column)
qSwap(row, column);
return (row * (row - ) / ) + column;
}

转自:http://qimo601.iteye.com/blog/1534331

(四)Qt实现自定义模型基于QAbstractTableModel (一般)的更多相关文章

  1. (五)Qt实现自定义模型基于QAbstractItemModel

    一个小例子 QTableView + QStandardItemModel QStandardItemModel model; //设置大小 model.setColumnCount(); //列 m ...

  2. Qt5MV自定义模型与实例浅析

    1. Model/View结构 这种结构,其实就是将界面组件与所编辑的数据分离开来,又通过数据源的方式连接起来,相当于解耦,视图层只关心显示和与用户交互,而数据层负责与实际的数据进行通信,并为视图组件 ...

  3. Qt的事件模型(5种使用办法,通常重新实现event handler即可。只有定义控件才需要管理信号的发射)

    Qt的事件模型 1.事件的概念 应用程序对象将系统消息接收为 Qt 事件.应用程序可以按照不同的粒度对事件加以监控.过滤并做出响应. 在 Qt 中,事件是指从 QEvent继承 的对象.Qt将事件发送 ...

  4. Qt之自定义托盘(二)

    上一篇文章讲述了自定义Qt托盘,不过不是使用QSystemTrayIcon这个类,而是我们自己完全自定义的一个类,我们只需要处理这个类的鼠标hover.鼠标左键点击.鼠标右键点击和鼠标左键双击,就可以 ...

  5. 一个I/O线程可以并发处理N个客户端连接和读写操作 I/O复用模型 基于Buf操作NIO可以读取任意位置的数据 Channel中读取数据到Buffer中或将数据 Buffer 中写入到 Channel 事件驱动消息通知观察者模式

    Tomcat那些事儿 https://mp.weixin.qq.com/s?__biz=MzI3MTEwODc5Ng==&mid=2650860016&idx=2&sn=549 ...

  6. QT中自定义系统托盘的实现—c++语言为例

    将要介绍的是:QT中自定义系统托盘(systemtray)的一个Demo,希望能帮需要的读者快速上手. 前提假设是诸位已经知道QT中的signals .slot以及资源文件,所以关于这些不会再累述. ...

  7. 封装:简要介绍自定义开发基于WPF的MVC框架

    原文:封装:简要介绍自定义开发基于WPF的MVC框架 一.目的:在使用Asp.net Core时,深感MVC框架作为页面跳转数据处理的方便,但WPF中似乎没有现成的MVC框架,由此自定义开发一套MVC ...

  8. [Qt插件]-03创建Qt Designer自定义部件

    如何创建自定义部件并添加到Qt Designer来爽快的拖动部件可视化界面设计?   Qt Designer基于插件的架构使得它可以使用用户设计或者第三方提供的自定义部件,就像使用标准的Qt部件一样. ...

  9. PyQt(Python+Qt)学习随笔:基于项的项部件(Item Widgets(Item-Based))概述

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 Model/View架构中的视图部件是基于模型的项视图(Item Views(Model-Based ...

随机推荐

  1. "Only the original thread that created a view hierarchy can touch its views.” 解决方法

    这个主要总是,开启的线程和 UI 线程(主线程)不是同一个线程.可以Runnable方式避免,如下例所示就可以解决这个问题了. public static void updateText(Activi ...

  2. selenium + python 怎样才能滚到页面的底部?

    可以用 execute_script方法来处理这个. 调用原生javascript的API,这样你想滚到哪里就能滚到哪里. 下面的代码演示了如何滚到页面的最下面:   driver.execute_s ...

  3. setContentView(R.layout.activity_main)无法正常引用

    今天在写Android代码的过程中,编译器一直报错,错误出在这一行代码: setContentView(R.layout.activity_main) 提示信息是: activity_main can ...

  4. 【转】对 Go 语言的综合评价

    以前写过一些对 Go 语言的负面评价.现在看来,虽然那些评价大部分属实,然而却由于言辞激烈,没有点明具体问题,难以让某些人信服.在经过几个月实际使用 Go 来构造网站之后,我觉得现在是时候对它作一些更 ...

  5. 兔子--eclipse设置编码格式

    设置编码格式 a:设置eclipse的默认编码格式:window->preferences->Workspace->Text File Encoding b:设置单个项目的编码格式: ...

  6. RUBY Error: Please update your PATH to include build tools or download the DevKit

    出错的原因是安装XXXXX的时候,需要build tools,但系统中没有.出错信息中同时也给出了解决的法案: 1. 到 http://rubyinstaller.org/downloads/ 去下载 ...

  7. 数据库分享一: MySQL的Innodb缓存相关优化

    无论是对于哪一种数据库来说,缓存技术都是提高数据库性能的关键技术,物理磁盘的访问速度永 远都会与内存的访问速度永远都不是一个数量级的.通过缓存技术无论是在读还是写方面都可以大大提 高数据库整体性能. ...

  8. Effective C++ Item 42 了解 typename 的双重意义

    本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:声明 template 參数时,前缀keyword class 和 typename ...

  9. C# xml可序列化多值枚举脚本

    代码: using System; using System.Collections.Generic; using System.Xml; using System.Xml.Schema; using ...

  10. ping域名和ping IP时速度不同的原因

    不知道大家在ping的时候有没有遇到过这样的问题:当你ping一个域名的时候,ping结果返回得很慢,但是如果直接ping这个域名的ip,结果却快很多. 直接ping ip的时候,每两次发包之间没有明 ...