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(¤cyModel); //设置交替颜色 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 = 0); 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, 0, 'f', 4); } 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 = 0); 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() - 1) / 2); //填充所有距离值为0 distances.fill(0); //刷新所有视图数据 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 0; 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 - 1) / 2) + column; }
转自:http://qimo601.iteye.com/blog/1534331