Qt — QTreeView и пользовательская модель со столбцами флажков

Я хотел иметь древовидное представление, которое показывает имя элемента, описание элемента и два связанных логических значения в соответствующих столбцах. Я начал с изменения примера редактируемого дерева, так что есть TreeModel, который отслеживает группу TreeItems, каждый из которых имеет не только список дочерних TreeItems, но также и список QVariant, в котором хранится набор значений, которые впоследствии могут отображаться в столбцах в QTreeView.

Мне удалось добавить еще два столбца для двух логических значений. Я также искал в сети, как добавить флажки для QTreeView и QAbstractItemModel. Мне удалось установить флажки в двух логических столбцах, а также в остальной части древовидной иерархии. Тем не менее, все элементы в каждом столбце теперь отображают флажок и строку текста.

Qt TreeView с флажками

Вот части, которые я изменил из примера, в основном в 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();

    …
}

Флажки под небулевыми столбцами не реагируют на ввод пользователя, а текст под логическими столбцами нельзя редактировать. Так что с точки зрения функциональности в этом нет ничего плохого, но это все еще утомительно с точки зрения пользовательского интерфейса.

Я перехожу к тому, чтобы QTreeWidget делал то же самое. Между тем, я не мог не задаться вопросом, есть ли что-то еще, что мне здесь не хватает. Я слышал, что одним из решений является использование собственного делегата; это единственный вариант?

Если есть кто-нибудь, кто может указать, что еще мне нужно сделать, или предоставить аналогичный пример, я буду очень признателен.


person Ingrid Wu    schedule 04.01.2013    source источник


Ответы (2)


Я думаю, что проблема в методе данных. Вы должны вернуть QVariant(), когда роль CheckStateRole, но столбец не является логическим.

person user2832323    schedule 19.03.2014

У меня была эта проблема. Это произошло в методе TreeModel::parent() из-за передачи значения child.column() в метод createIndex(). Вместо этого должно быть 0. Итак, вместо

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

должно быть

createIndex(parentItem->childNumber(), 0, parentItem);
person user3605398    schedule 14.12.2017