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;
- }