如何在 QModelView 中组合模式对话框编辑器和就地小组件编辑器

How to combine modal dialog editor and in-place widget editor in QModelViews?

本文关键字:编辑器 组件 对话框 模式 QModelView 组合      更新时间:2023-10-16

我有一个包含简单和复杂数据的模型,我想使用就地小部件来编辑简单数据,但模式对话框来编辑复杂数据......我怎样才能以干净的方式实现这一目标?(我真的更愿意通过QItemDelegate的子类做所有事情,并且没有特定于视图的hack)

我认为您必须对视图进行子类化并覆盖QAbstractItemView::edit()函数以处理不同的编辑路径。例如:

class MyView : public QTreeView
{
    [..]
protected:
    bool edit(const QModelIndex &index, EditTrigger trigger, QEvent *event)
    {
        if (index.row() > 5) { // Use your own criteria for simple/complex data
            // Simple data with default editor.
            return QTreeView::edit(index, trigger, event);
        } else {
            // Edit complex data.
            QDialog dialog;
            dialog.exec();
            return false;
        }
    }
    [..]
};

尝试下一个委托。我在示例中显示了主要思想:

页眉:

#ifndef ITEMDELEGATE_H
#define ITEMDELEGATE_H
#include <QItemDelegate>
class ItemDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    explicit ItemDelegate(QObject *parent = 0);
protected:
    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    void setEditorData(QWidget * editor, const QModelIndex & index) const;
    void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const;
    void updateEditorGeometry(QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & index) const;
    bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);
signals:
public slots:
};
#endif // ITEMDELEGATE_H

我只向您展示editorEvent因为您可以自己编写的所有其他方法,它将是自定义委托,但editorEvent我们创建模态对话框。

bool ItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
                               const QStyleOptionViewItem &option,
                               const QModelIndex &index)
{
    if(index.row()%2)//specific items, you can use it another options, it is just example
    {
        QInputDialog* dia = new QInputDialog;//create dialog, just example, it can be your QDialog subclass        
        dia->setInputMode(QInputDialog::TextInput);
        //dia->setAttribute(Qt::WA_DeleteOnClose);
        dia->setModal(true);
        connect(dia, &QInputDialog::finished,[=]()//connection which will take data from dialog
        {
           model->setData(index,dia->textValue());//provide some method in your dialog to get user data and set it in model 
           delete dia;//we don't want memory leaks
         });
        dia->show();
    }
    return QItemDelegate::editorEvent(event,model,option,index);
}

我在这里使用了C++11CONFIG += c++11.pro文件)以及信号和插槽的新语法

这是一个

老问题,但考虑到这两个答案在生产上都不令人满意(返回 false 时崩溃、嵌套事件循环等)......请注意,我并没有责怪海报说"那样不能干净利落地完成"。

一个完全不同的、受支持的方法怎么样?

我之前有这样的实现(伪代码):

  1. 禁用"复杂"项的编辑触发器

.

auto item = model->item(row, column);
item->setFlags(item->flags() & ~Qt::ItemFlag::ItemIsEditable); // not editable
  1. 连接到QAbstractItemView::activated

忽略"简单"项的事件

connect(m_ui.tableView,
  &QAbstractItemView::activated,
  this,
  &QtGuiApplication2::onDataActivated);
//...
void QtGuiApplication2::onDataActivated(const QModelIndex &index) {
  if(!is_complex)
    return;
  EditDialog dlg;
  if(dlg.exec() == QDialog::DialogCode::Accepted) {
    updatemodel();
  }
}
  1. 项目委托:忽略"复杂"项。

    QWidget* VariableEditorDelegate::createEditor(QWidget *parent,
    const QStyleOptionViewItem &option,
    const QModelIndex &index) const {
      if(is_complex)
        return nullptr; // same as base class
      return new EditorWidget(parent);
    }
    

当然,这并不像只有代表那么好,但至少它不会在崩溃时如此紧密地绕过。