在 QTreeview 特定单元格中添加 QCombobox

问题描述

我试图仅在 QTreeview 的某些特定单元格中插入 QComboBox。当我阅读时,我认为我需要创建我的委托(我已经创建)。但我不明白如何在我的树视图中插入它。

我想意识到这一点:

enter image description here

这是我的代码

#include <QTreeView>
#include <QStandardItemmodel>
#include <QStandardItem>
#include "mainwindow.h"
#include "comboBoxdelegate.h"


const int ROWS = 2;
const int COLUMNS = 3;

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    treeView = new QTreeView(this);
    setCentralWidget(treeView);

    standardModel = new QStandardItemmodel ;
    standardModel->setColumnCount(2);

    QStandardItem *root = new QStandardItem("ROOT");
    root->setCheckable(true);
    root->setCheckState(Qt::Checked);
    root->setEditable(false);

    standardModel->setItem(0,root);

    QList< QStandardItem * > listOne ;
    QStandardItem  *f1 = new QStandardItem( "Field_1" );
    f1->setCheckable(true);
    f1->setCheckState(Qt::Checked);
    f1->setEditable(false);

    listOne.append(f1) ;
    listOne.append( new QStandardItem( "<Free text>" ) ) ;
    root->appendRow(listOne);


    QList< QStandardItem * > listTwo ;
    QStandardItem  *f2 = new QStandardItem( "Field_2" );
    listTwo.append(f2) ;
    listTwo.append( new QStandardItem( "<HERE COMBOBox!>" ) ) ;
    root->appendRow(listTwo);

    treeView->setModel(standardModel);
    treeView->expandAll();
}

我设法使用 QComboBox(使用自定义委托)创建了一整列。但我不知道如何只设置特定的单元格。任何人都可以帮助我吗?

解决方法

QTreeWidget 使小部件项目变得方便。

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    treeWidget = new QTreeWidget(this);
    setCentralWidget(treeWidget);

    treeWidget->setColumnCount(2);

    auto root = new QTreeWidgetItem({"Root"});
    root->setCheckState(0,Qt::Checked);
    treeWidget->addTopLevelItem(root);

    auto child1 = new QTreeWidgetItem({"Field 1","<Free Text>"});
    child1->setCheckState(0,Qt::Checked);
    child1->setFlags(child1->flags() | Qt::ItemIsEditable);
    root->addChild(child1);

    auto child2 = new QTreeWidgetItem({"Field 2"});
    child2->setFlags(child2->flags() | Qt::ItemIsEditable);
    root->addChild(child2);

    auto comboBox = new QComboBox();
    comboBox->addItems({"Red","Blue","Yellow"});
    treeWidget->setItemWidget(child2,1,comboBox);

    connect(treeWidget,&QTreeWidget::itemDoubleClicked,treeWidget,&QTreeWidget::editItem);

    treeWidget->expandAll();
}

需要注意一些差异。

  • 您需要在类声明中使用 QTreeWidget* treeWidget;。并包含 QTreeWidget 标头。

  • 默认情况下,TreeWidgetItems 不可检查(无复选框),但使用 QTreeWidgetItem::setCheckStateQt::Checked 调用 Qt::Unchecked 将使其可检查。

  • 默认情况下项目不可编辑。可以通过调用 treeWidgetItem->setFlags(treeWidgetItem->flags() | Qt::ItemIsEditable) 使整个 成为可编辑的。要过滤可以编辑的行/列,您可以定义自己的 itemDoubleClicked 槽并使用 if 语句 (example)。

,

您需要将组合框项存储在模型项中,例如使用 Qt::UserRole

QStringList options = {"one","two","three"};
QStandardItem* item = new QStandardItem(options[0]);
item->setData(QVariant(options),Qt::UserRole);
listTwo.append(item);

然后您需要分配代理才能查看。您可以为整个表分配它并在 index.data(Qt::UserRole).isNull() 时返回默认委托。

Delegate* delegate = new Delegate(treeView);
treeView->setItemDelegate(delegate);

将编辑触发器设置为所有可能是个好主意,因此下拉不仅在双击时发生,而且在单击时发生

treeView->setEditTriggers(QAbstractItemView::AllEditTriggers);

委托必须实现 createEditorsetEditorDatasetModelData

QWidget *Delegate::createEditor(QWidget *parent,const QStyleOptionViewItem &option,const QModelIndex &index) const
{
    if (index.data(Qt::UserRole).isNull()) {
        return QStyledItemDelegate::createEditor(parent,option,index);
    }
    return new QComboBox(parent);
}

void Delegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{
    QComboBox* comboBox = qobject_cast<QComboBox*>(editor);
    if (!comboBox) {
        return QStyledItemDelegate::setEditorData(editor,index);
    }
    QStringList options = index.data(Qt::UserRole).toStringList();
    comboBox->addItems(options);
    QString value = index.data().toString();
    int current = options.indexOf(value);
    if (current > -1) {
        comboBox->setCurrentIndex(current);
    }
    comboBox->showPopup();
}

void Delegate::setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex &index) const
{
    QComboBox* comboBox = qobject_cast<QComboBox*>(editor);
    if (!comboBox) {
        return QStyledItemDelegate::setModelData(editor,model,index);
    }
    model->setData(index,comboBox->currentText());
}

默认情况下,委托不会更改项目的显示方式,仅在触发编辑时才显示编辑器:不显示组合框。但您可以使用自定义 paintEvent 覆盖它。

void Delegate::paint(QPainter *painter,const QModelIndex &index) const
{
    if (index.data(Qt::UserRole).isNull()) {
        return QStyledItemDelegate::paint(painter,index);
    }
    QStyle* style = qApp->style();
    QStyleOptionComboBox opt;
    opt.rect = option.rect;
    opt.currentText = index.data().toString();
    opt.palette = option.palette;
    opt.state = option.state;
    opt.subControls = QStyle::SC_All;
    opt.activeSubControls = QStyle::SC_All;
    opt.editable = false;
    opt.frame = true;
    style->drawComplexControl(QStyle::CC_ComboBox,&opt,painter,0);
    style->drawControl(QStyle::CE_ComboBoxLabel,0);
}

完整来源:combobox-delegate