很遗憾,模型 API 并没有提供很好的方法来做到这一点。最简单的解决方案是让您的模型根据当前使用的根索引返回不同的headerData。但是,这意味着模型需要知道视图的状态(更具体地说,是根索引),这不是您通常想要的。
我认为设置代理模型可能是解决此问题的一种优雅方法。以下是它的实现方式:
class ChildHeadersProxy : public QSortFilterProxyModel {
public:
static const int HorizontalHeaderRole = Qt::UserRole + 1;
static const int VerticalHeaderRole = Qt::UserRole + 2;
void setRootIndex(const QModelIndex& index) {
m_rootIndex = index;
if (sourceModel()) {
emit headerDataChanged(Qt::Horizontal, 0, sourceModel()->columnCount(m_rootIndex));
emit headerDataChanged(Qt::Vertical, 0, sourceModel()->rowCount(m_rootIndex));
}
}
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const {
if (sourceModel() && m_rootIndex.isValid()) {
int role = orientation == Qt::Horizontal ? HorizontalHeaderRole : VerticalHeaderRole;
QStringList headers = sourceModel()->data(m_rootIndex, role).toStringList();
if (section >= 0 && section < headers.count()) {
return headers[section];
}
}
return QSortFilterProxyModel::headerData(section, orientation, role);
}
private:
QModelIndex m_rootIndex;
};
此代理模型使用源模型通过两个自定义角色提供的标头。比如你使用QStandardItemModel,设置headers就这么简单:
model.item(0, 1)->setData(QStringList() << "h1" << "h2",
ChildHeadersProxy::HorizontalHeaderRole);
model.item(0, 1)->setData(QStringList() << "vh1" << "vh2",
ChildHeadersProxy::VerticalHeaderRole);
其中model.item(0, 1) 是对应的根项。设置视图如下所示:
QTableView view;
ChildHeadersProxy proxy;
proxy.setSourceModel(&model);
view.setModel(&proxy);
更改根索引将如下所示:
view.setRootIndex(proxy.mapFromSource(model.index(0, 1)));
proxy.setRootIndex(model.index(0, 1));