Qt - QTreeView 和带有复选框列的自定义模型

Posted

技术标签:

【中文标题】Qt - QTreeView 和带有复选框列的自定义模型【英文标题】:Qt - QTreeView and custom model with checkbox columns 【发布时间】:2013-01-04 13:33:57 【问题描述】:

我想要一个树形视图,在相应的列中显示项目名称、项目描述和两个相关的布尔值。我从修改Editable Tree Mode example 开始,所以有一个TreeModel 跟踪一组TreeItem,每个TreeItem 不仅有一个子TreeItem 列表,还有一个QVariants 列表,其中存储了一组值,以后可以显示在 QTreeView 的列中。

我设法为两个布尔值添加了另外两列。我还在网上搜索了如何为 QTreeView 和 QAbstractItemModel 添加复选框。我设法让两个布尔列上的复选框以及树层次结构的其余部分正常工作。然而,每列中的所有项目现在都呈现一个复选框和一行文本。

这是我从示例中修改的部分,主要在 TreeModel 中。

treemodel.cpp:

bool TreeModel::isBooleanColumn( const QModelIndex &index ) const

    bool bRet = false;
    if ( !index.isValid() )
    
    
    else
    
        bRet = ( index.column() == COLUMN_BOL1 ) || ( index.column() == COLUMN_ BOL2 );
    
    return bRet;


Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const

    if (!index.isValid())
        return 0;
    if ( isBooleanColumn( index ) )
    
        return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
    
    else
    
        return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    


QVariant TreeModel::data(const QModelIndex &index, int role) const

    if (!index.isValid())
        return QVariant();
    if (role != Qt::DisplayRole && role != Qt::EditRole && role != Qt::CheckStateRole )
        return QVariant();
    TreeItem *item = getItem(index);
    if ( role == Qt::CheckStateRole && isBooleanColumn( index ) )
    
        Qt::CheckState eChkState = ( item->data( index.column() ).toBool() ) ? Qt::Checked : Qt::Unchecked;
        return eChkState;
    
    return item->data(index.column());


bool TreeModel::setData(const QModelIndex &index, const QVariant &value,
                        int role)

    if (role != Qt::EditRole && role != Qt::CheckStateRole )
        return false;
    TreeItem *item = getItem(index);
    bool result;
    if ( role == Qt::CheckStateRole && isBooleanColumn( index ) )
    
        Qt::CheckState eChecked = static_cast< Qt::CheckState >( value.toInt() );
        bool bNewValue = eChecked == Qt::Checked;
        result = item->setData( index.column(), bNewValue );
    
    else
    
        result = item->setData(index.column(), value);
    
    if (result)
        emit dataChanged(index, index);
    return result;

ma​​inwindow.cpp:

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)

    …
    QStringList headers;
    headers << tr("Title") << tr("Description") << tr("Hide") << tr("Lock");
    QFile file(":/default.txt");
    file.open(QIODevice::ReadOnly);
    TreeModel *model = new TreeModel(headers, file.readAll());
    file.close();

    …

非布尔列下的复选框不响应用户输入,并且布尔列下的文本不可编辑。所以在功能方面没有什么问题,但就 UI 而言仍然很麻烦。

我打算让 QTreeWidget 做同样的事情。同时,我不禁想知道我在这里是否还缺少其他东西。我听说一种解决方案是有一个自定义委托;这是唯一的选择吗?

如果有人能指出我还需要做什么,或提供类似的例子,我将不胜感激。

【问题讨论】:

【参考方案1】:

我认为问题出在 Data 方法中。当角色为 CheckStateRole 但列不是布尔值时,您应该返回 QVariant()。

【讨论】:

【参考方案2】:

我遇到了这个问题。由于将 child.column() 值传递给 createIndex() 方法,它发生在 TreeModel::parent() 方法中。它应该是 0。所以,而不是

createIndex(parentItem->childNumber(), child.column(), parentItem);

应该是

createIndex(parentItem->childNumber(), 0, parentItem);

【讨论】:

以上是关于Qt - QTreeView 和带有复选框列的自定义模型的主要内容,如果未能解决你的问题,请参考以下文章

Qt窗口及控件-QTreeview/QTableView排序问题

自定义 QTreeView 项目

QTreeView 和 QTableView 的 Qt 模型

C# treeview 获得选中值

将复选框列添加到树左侧的 QTreeView 的方法?

无论如何在qt的同一个窗口中放置一个QTreeView和一个QChartView?