一般的,QSqlTableModel可以關聯數據庫的一張表,QTableView對象通過setModel,關聯這個model對象,這樣,編碼上很方便能將QTableView展示成數據庫表的樣式。
但是如果數據來源不是數據庫表,而是json數組,則需要繼承QAbstractTableModel,然後再讓tableview->setModel。
下文的AbsTblMdlJsonArray就簡易地實現了這個功能。
#pragma once
#include <memory>
#include <QAbstractTableModel>
#include <QJsonArray>
class AbsTblMdlJsonArray : public QAbstractTableModel {
public:
AbsTblMdlJsonArray(const QJsonArray &src, QObject *parent = Q_NULLPTR);
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
//QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
//QModelIndex parent(const QModelIndex &index) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
protected:
QJsonArray m_src;
int m_rowCount;
int m_columnCount = 0;
QVariantMap m_vmapHead;
std::unique_ptr<QString[]> m_headers;
QList<QVariantMap> m_data;
QString currencyAt(int offset) const;
};
#include <QJsonObject>
#include "AbsTblMdlJsonArray.h"
AbsTblMdlJsonArray::AbsTblMdlJsonArray(const QJsonArray &src, QObject *parent)
: QAbstractTableModel(parent)
, m_src(src)
, m_rowCount(src.count())
{
if (m_rowCount > 0) {
for (auto it = m_src.constBegin(); it != m_src.constEnd(); ++it) {
if (it->isObject()) {
m_data.push_back(it->toObject().toVariantMap());
}
}
m_vmapHead = m_data.front();
m_columnCount = m_vmapHead.count();
m_headers = std::make_unique<QString[]>(m_columnCount);
auto keys = m_vmapHead.keys();
int i = 0;
for (const auto &each : keys) {
m_headers[i++] = each;
}
}
}
int AbsTblMdlJsonArray::columnCount(const QModelIndex &parent) const {
return m_columnCount;
}
QString AbsTblMdlJsonArray::currencyAt(int offset) const {
return (m_vmapHead.begin() + offset).key();
}
QVariant AbsTblMdlJsonArray::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) {
const auto row = m_data.at(index.row());
return row.find(m_headers[index.column()]).value();
}
return QVariant();
}
int AbsTblMdlJsonArray::rowCount(const QModelIndex &parent) const {
return m_rowCount;
}
QVariant AbsTblMdlJsonArray::headerData(int section, Qt::Orientation orientation, int role) const {
if (role == Qt::DisplayRole)
{
if (orientation == Qt::Horizontal) // ˮƽҭͷ
{
return m_headers[section];
}
}
return QVariant();
}
使用範例如下:
ui.setupUi(this);
QString str("[ {\"a\":1,\"b\":0.1,\"c\":\"xx\"},\
{\"a\":2,\"b\":0.2,\"c\":\"yy\"},\
{\"a\":2,\"b\":0.2,\"c\":\"zz\"}]");
QJsonParseError err;
QJsonDocument jd = QJsonDocument::fromJson(str.toUtf8(), &err);
QJsonArray ja = jd.array();
m_data = std::make_unique<AbsTblMdlJsonArray>(ja, this);
ui.tableView->setModel(m_data.get());