【问题标题】:Add QCombobox inside QTreeview specific cell在 QTreeview 特定单元格中添加 QCombobox
【发布时间】:2021-06-27 07:03:38
【问题描述】:

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

我想实现这一点:

这是我的代码:

#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, 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 创建了一个完整的列(使用自定义委托)。但我不知道如何只设置特定的单元格。谁能帮帮我?

【问题讨论】:

    标签: c++ qt qwidget qtreeview qcombobox


    【解决方案1】:

    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 是不可检查的(无复选框),但使用 Qt::CheckedQt::Unchecked 调用 QTreeWidgetItem::setCheckState 将使其可检查。

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

    【讨论】:

    • 谢谢!我决定将我的 QTreeview 转换为 QTreeWidget。更灵活。
    【解决方案2】:

    您需要将组合框项目存储在模型项目中,例如使用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 QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        if (index.data(Qt::UserRole).isNull()) {
            return QStyledItemDelegate::paint(painter, option, 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, &opt, painter, 0);
    }
    

    完整来源:combobox-delegate

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-26
      • 1970-01-01
      • 2016-11-13
      • 1970-01-01
      • 2018-12-02
      相关资源
      最近更新 更多