转载自:https://blog.51cto.com/9291927/1890098
一、QAbstractItemModel为自定义模型提供了一个足够灵活的接口,能够支持数据源的层次结构,能够对数据进行增删改操作,还能够支持拖放。QT提供了 QAbstarctListModel和QAbstractTableModel两个类来简化非层次数据模型的开发,适合于结合列表和表格使用。
自定义模型需要考虑模型管理的的数据结构适合的视图的显示方式。如果模型的数据仅仅用于列表或表格的显示,那么可以使用QAbstractListModel或者 QAbstractTableModel。但如果模型的数据具有层次结构,并且必须向用户显示出层次结构,只能选择QAbstractItemModel。不管底层数据结构是如何组织的,都要直接考虑适应于标准的 QAbstractItemModel的接口,可以让更多视图能够轻松访问到模型。
CurrencyModel.h文件:
#ifndef CURRECYMODEL_H #define CURRECYMODEL_H #include <QAbstractTableModel> #include <QAbstractItemModel> #include <QMap> class CurrecyModel : public QAbstractTableModel { Q_OBJECT public: explicit CurrecyModel(QObject *parent = 0); // Header: QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; // Basic functionality: int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; Qt::ItemFlags flags(const QModelIndex &index) const; bool setData(const QModelIndex &index, const QVariant &value,int role = Qt::EditRole); void setCurrencyMap(const QMap<QString, double> &map); private: QString currencyAt(int offset) const; QMap<QString, double> currencyMap; }; #endif // CURRECYMODEL_H
CurrencyModel.cpp文件:
#include "CurrecyModel.h" CurrecyModel::CurrecyModel(QObject *parent) : QAbstractTableModel(parent) { } QVariant CurrecyModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role != Qt::DisplayRole) { return QVariant(); } return currencyAt(section); } int CurrecyModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) return 0; return currencyMap.count(); } int CurrecyModel::columnCount(const QModelIndex &parent) const { if (parent.isValid()) return 0; return currencyMap.count(); } QVariant CurrecyModel::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 || role == Qt::EditRole) { 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(); } bool CurrecyModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (index.isValid() && index.row() != index.column() && role == Qt::EditRole) { QString columnCurrency = headerData(index.column(), Qt::Horizontal, Qt::DisplayRole).toString(); QString rowCurrency = headerData(index.row(), Qt::Vertical, Qt::DisplayRole).toString(); currencyMap.insert(columnCurrency, value.toDouble() * currencyMap.value(rowCurrency)); emit dataChanged(index, index); return true; } return false; } Qt::ItemFlags CurrecyModel::flags(const QModelIndex &index) const { Qt::ItemFlags flags = QAbstractItemModel::flags(index); if (index.row() != index.column()) { flags |= Qt::ItemIsEditable; } return flags; } QString CurrecyModel::currencyAt(int offset) const { return (currencyMap.begin() + offset).key(); } void CurrecyModel::setCurrencyMap(const QMap<QString, double> &map) { beginResetModel(); currencyMap = map; endResetModel(); }
在MainWindow中ui中添加QTableView表格控件。
MainWindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" #include "CurrecyModel.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QMap<QString, double> data; data["USD"] = 1.0000; data["CNY"] = 0.1628; data["GBP"] = 1.5361; data["EUR"] = 1.2992; data["HKD"] = 0.1289; CurrecyModel *model = new CurrecyModel(this); ui->tableView->setModel(model); model->setCurrencyMap(data); } MainWindow::~MainWindow() { delete ui; }
效果图如下: