參考:qt源碼
qstandarditemmodel_p.h
qstandarditemmodel.h
qstandarditemmodel.cpp
qabstractitemmodel.h
qabstractitemmodel.cpp
QAbstractItemModel是一個接口類,使用時需要從它繼承下來,實現相關的函數后使用。
不同於QStandardItemModel,使用QAbstractItemModel的話,需要自己構造樹形結構數據,並在虛函數中返回對應的值。
當然,簡單使用的話,也可以快速構造出沒有父節點的簡單表格結構。
形如根節點下列了幾排幾列子節點的表格情形。
需要繼承的類有:
class HistoryModel : public QAbstractItemModel
{
public:
explicit HistoryModel(QObject *parent = 0);
// 構造父節點下子節點的索引
virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
// 通過子節點索引獲取父節點索引
virtual QModelIndex parent(const QModelIndex &child) const override;
// 獲取父節點下子節點的行數
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
// 獲取父節點下子節點列數
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override;
// 獲取節點數據:包括DisplayRole|TextAlignmentRole等
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
實現幾排幾列表格情形的例子:
HistoryModel::HistoryModel(QObject *parent /*= 0*/)
: QAbstractItemModel(parent)
{
}
QModelIndex HistoryModel::index(int row, int column, const QModelIndex &parent /*= QModelIndex()*/) const
{
// 創建普通索引
return createIndex(row, column);
}
QModelIndex HistoryModel::parent(const QModelIndex &child) const
{
// 父節點均為跟節點
return QModelIndex();
}
int HistoryModel::rowCount(const QModelIndex &parent /*= QModelIndex()*/) const
{
// 根節點下有5行,其它行下沒有
if (parent.row() == -1)
{
return 5;
}
return 0;
}
int HistoryModel::columnCount(const QModelIndex &parent /*= QModelIndex()*/) const
{
// 每行有量列
return 2;
}
QVariant HistoryModel::data(const QModelIndex &index, int role /*= Qt::DisplayRole*/) const
{
// 節點內容:左對齊,顯示行列號
if (role == Qt::TextAlignmentRole)
return int(Qt::AlignLeft | Qt::AlignVCenter);
else if (role == Qt::DisplayRole)
return QString("row=%1,col=%2").arg(index.row()).arg(index.column());
else
return QVariant();
}
進一步使用,添加樹形結構,自己構造樹形結構數據:
struct NodeInfo
{
QModelIndex parent; // 父節點index
QString sData; // 自身數據
QVector<NodeInfo*> childNodes; // 子節點
NodeInfo(QModelIndex parentIdx, QString s):parent(parentIdx), sData(s){}
};
1
2
3
4
5
6
7
生成如下的這種界面:兩個level=1節點,每個節點下有一些數據
可以這樣來做:
每個節點存儲一個NodeInfo信息,這樣
1. 每個節點可以查詢子節點數量
2. 每個節點可以查詢到自身數據
3. 可以根據NodeInfo信息(row/col/this)獲取到QModeIndex
4. 數據構造時,形成NodeInfo的樹形層次
5. QAbstractItemModel的接口中,index函數中綁定NodeInfo
6. QAbstractItemModel的其它接口中,查詢NodeInfo並使用
HistoryModel::HistoryModel(QObject *parent /*= 0*/)
: QAbstractItemModel(parent)
{
// 創建root節點
m_pRootNode = new NodeInfo(nullptr, "rootNode", -1, -1);
m_receiveInfo = new NodeInfo(m_pRootNode, "ReceiveMessage", 0, 0);
m_replyInfo = new NodeInfo(m_pRootNode, "ReplyMessage", 1, 0);
m_pRootNode->childNodes.append(m_receiveInfo);
m_pRootNode->childNodes.append(m_replyInfo);
}
QModelIndex HistoryModel::index(int row, int column, const QModelIndex &parent /*= QModelIndex()*/) const
{
if (parent.row() == -1 && parent.column() == -1)
{
// 首層節點綁定關系
if (row < m_pRootNode->childNodes.count())
return createIndex(row, column, m_pRootNode->childNodes[row]);
}
else
{
// 其它層節點綁定關系
if (parent.internalPointer() != nullptr)
{
NodeInfo* pNode = reinterpret_cast<NodeInfo*>(parent.internalPointer());
if (pNode->childNodes.size() > row)
{
return createIndex(row, column, pNode->childNodes[row]);
}
}
}
return QModelIndex();
}
QModelIndex HistoryModel::parent(const QModelIndex &child) const
{
if (child.internalPointer() != nullptr)
{
NodeInfo* pNode = reinterpret_cast<NodeInfo*>(child.internalPointer());
NodeInfo* pParent = pNode->parent;
if (pParent != nullptr)
{
// 根據父節點信息:row/col/node*獲取Index
return createIndex(pParent->nRow, pParent->nCol, pParent);;
}
}
return QModelIndex();
}
int HistoryModel::rowCount(const QModelIndex &parent) const
{
if (parent.internalPointer() == nullptr)
{
// 根節點下的數據行數
return m_pRootNode->childNodes.count();
}
else
{
// 節點下的數據行數
NodeInfo* pNode = reinterpret_cast<NodeInfo*>(parent.internalPointer());
return pNode->childNodes.size();
}
}
int HistoryModel::columnCount(const QModelIndex &parent /*= QModelIndex()*/) const
{
// 每行有量列
return 1;
}
QVariant HistoryModel::data(const QModelIndex &index, int role /*= Qt::DisplayRole*/) const
{
// 節點內容:左對齊,顯示行列號
if (role == Qt::TextAlignmentRole)
{
return int(Qt::AlignLeft | Qt::AlignVCenter);
}
else if (role == Qt::DisplayRole)
{
if (index.internalPointer() == 0)
{
return QString("row=%1,col=%2").arg(index.row()).arg(index.column());
}
else
{
NodeInfo* pNode = reinterpret_cast<NodeInfo*>(index.internalPointer());
return pNode->sData;
}
}
else
{
return QVariant();
}
}
(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)
---------------------
作者:春夜喜雨
來源:CSDN
原文:https://blog.csdn.net/chunyexiyu/article/details/77657624
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
void wokr() { QModelIndex index = model.getIndex(); ... ... return; // 局部變量,函數退出時自動回收。 } std::string func() { return "123"; } 你需要管返回值誰釋放嘛? 奇怪的問題 std::string* func() { return new std::string("123"); } 但是這個你就要關心了