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

时间:2013-01-04 13:33:58

标签: qt checkbox qtreeview qabstractitemmodel

我希望有一个树形视图,显示项目名称,项目描述以及相应列中的两个相关布尔值。我开始修改Editable Tree Mode example,所以有一个TreeModel跟踪一组TreeItems,每个TreeItems不仅有一个子TreeItems列表,而且还有一个QVariants列表,它存储了一组值可以稍后将显示在QTreeView的列中。

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

Qt TreeView with Checkboxes

这是我从示例中修改的部分,主要是在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;
}

mainwindow.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做同样的事情。与此同时,我不禁想知道这里是否还有别的东西。我听说一个解决方案就是拥有一个自定义代表;这是唯一的选择吗?

如果有人可以指出我还需要做什么,或提供类似的例子,我将非常感激。

2 个答案:

答案 0 :(得分:1)

我认为问题出在Data方法中。你应该返回QVariant()当角色是CheckStateRole但是列不是boolean。

答案 1 :(得分:0)

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

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

应该是

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