【问题标题】:QTreeView: hierarchical context for multi-level columnsQTreeView:多级列的分层上下文
【发布时间】:2015-09-23 21:08:17
【问题描述】:

我正在寻找一种在树中显示多级分层数据的更好方法,其中每列的含义会根据树中的级别而变化

我正在使用QTreeViewQAbstractItemModel 来显示我的模型数据。

每个模型行都有不同的列数不同的列名,具体取决于其在层次结构中的级别。

为了给树中显示的数据提供上下文,我需要为层次结构中的每个级别设置列标题。

问题是QTreeView 只有一组列标题。

当前方法

目前,每次所选行更改时,我都会更改标题。

我通过连接到树视图的selectionModel 来做到这一点,并在每次选择更改时使用新的QModelIndex 发出信号

void Window::slotOnSelectionChanged(const QItemSelection& new_selection, const QItemSelection& old_selection)
{
    QItemSelectionModel* selection_model = _view->selectionModel();
    QModelIndex index = selection_model->currentIndex();
    if (index.isValid())
        emit selectedIndexChanged(index);
}

在我的模型中,我连接到这个信号,当它触发时,存储选定的行,并强制更新列标题

void Model::slotOnSelectedIndexChanged(QModelIndex index)
{
    assert(index.isValid());
    _selected_row = modelRow(index);
    emit headerDataChanged(Qt::Horizontal, 0, _root->numColumns());
}

QAbstrateItemModel::headerData 回调中,我使用selected_row 获取当前选定行的标题

QVariant Model::headerData(int i, Qt::Orientation orientation, int role) const
{
    if (role == Qt::DisplayRole)
    {
        switch (orientation)
        {
            case Qt::Horizontal:
                return QVariant(_selected_row->header(i));
            ...

结果

结果如下所示 - 注意列标题​​如何随着所选行的变化而变化。

问题

仅通过查看每个数据的视图并不能立即看出这一点,因此用户需要更改行才能看到每列的实际含义。

我想要的是有某种嵌入的列标题行,层次结构中的每级 1 个。

类似这样的:

问题

  • 这可能吗?
  • 如果有更好的方法为树中的数据提供上下文,请提供建议。

【问题讨论】:

  • 通过在树中添加额外的元素而不使用标题视图当然是可能的。您可以通过视图模型代理来执行此操作 - 一种仅用于以您希望的方式查看数据的代理。
  • 额外元素不会显示为附加行而不是现有行的一部分吗?
  • 我对视图模型代理一无所知,我会继续阅读。感谢您的建议
  • 本身没有 Qt 文档。 viewmodel 是一个抽象概念,有多种可能的实现,甚至有多种实现类。一种是视图模型提供数据来布局控件。另一种是当视图模型为特定的显示场景调整来自另一个模型的数据时。
  • 感谢您的建议 - 我几乎已经完全找到了我想要的东西 - 向你致敬!我已经添加了一个答案,其中包含将您的建议付诸实践的详细信息,以供后代使用

标签: c++ qt qtreeview qabstractitemmodel


【解决方案1】:

@Kuba Ober 的建议下,我在树的每个层次结构的位置 0 处添加了一个额外的行。它没有孩子。

然后将模型配置为index.row() == 0 的特殊情况,知道该行是标题行而不是数据行。

例如:Model::flags 中的标题行不可编辑

Qt::ItemFlags Model::flags(const QModelIndex& index) const
{
    Qt::ItemFlags item_flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;

    // header row is not editable
    if (index.row() != 0)
        item_flags |= Qt::ItemIsEditable;

    return item_flags;
}

我现在为 headerData 返回空字符串,因为标题在树本身中

QVariant Model::headerData(int i, Qt::Orientation orientation, int role) const
{
    if (role == Qt::DisplayRole)
    {
        switch (orientation)
        {
            case Qt::Horizontal:
                return QVariant(); // no column header, it's already in the tree
            ...

我还更改了标题的背景颜色,使其突出

QVariant Model::data(const QModelIndex& index, int role)  const
{
    switch (role)
    {
        case Qt::BackgroundColorRole:
            if (index.row() == 0) // header row
                return QColor(Qt::darkGray);
            break;
        ...

结果几乎就是我想要的结果

【讨论】:

    猜你喜欢
    • 2015-03-10
    • 1970-01-01
    • 1970-01-01
    • 2011-07-30
    • 2012-07-25
    • 2016-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多