【问题标题】:Making only one column of a QTreeWidgetItem editable仅使 QTreeWidgetItem 的一列可编辑
【发布时间】:2010-05-10 10:40:14
【问题描述】:

我有一个包含两列数据的QTreeWidgetItem,有没有办法只使第二列可编辑?当我执行以下操作时:

QTreeWidgetItem* item = new QTreeWidgetItem();
item->setFlags(item->flags() | Qt::ItemIsEditable);

所有列都可以编辑。

【问题讨论】:

    标签: c++ qt flags qtreewidgetitem


    【解决方案1】:

    您可以使用解决方法仅使 QTreeWidget 中的某些列可编辑:

    1) 设置QTreeWidget的editTriggers属性为NoEditTriggers

    2) 在插入项目时,设置 QTreeWidgetItem 对象的 Qt:ItemIsEditable 标志

    3) 将以下槽连接到 QTreeWidget 对象的“itemDoubleClicked”信号:

    void MainWindow::onTreeWidgetItemDoubleClicked(QTreeWidgetItem * item, int column)
    {
        if (isEditable(column)) {
            ui.treeWidget->editItem(item, column);
        }
    }
    

    其中“isEditable”是您编写的函数,它对可编辑列返回 true,对不可编辑列返回 false。

    【讨论】:

    • 对我来说最好的解决方案。谢谢!
    • 双击不是开始编辑的唯一方法,还有很多其他的编辑触发器(任何键,编辑键(Windows/Linux 上的 F2),当前项目更改等。等)取决于配置(setEditTriggers)。所以这似乎有点不完整。
    • 我同意,@DavidFaure。我的解决方案易于理解且经过良好测试,但需要一些工作来实现多个编辑触发器。如果需要多个编辑触发器,我推荐 user571167 的 NoEditDelegate 解决方案。
    • @d11 一旦变为可编辑,是否可以设置输入策略?(使用 QRegExp 和 QRegExpValidator)就像只有数字有效,否则不接受输入?我想不通。
    • @bear 在您的情况下,优雅的解决方案是将项目委托子类化为 user571167 在解决方案中的子类,但不是实现 NoEditDelegate,而是将您在 createEditor 中创建的编辑器连接到您的 @987654324 @。请参阅here 了解 Qt 的讨论以及如何将子类化为项目委托的示例。
    【解决方案2】:

    我最近遇到了同样的问题,并发现了一个适用于所有 EditTriggers 的解决方案,而不仅仅是 DoubleClicked 的(以及与双击信号的连接)

    创建一个代表,它为编辑器返回一个空指针:

    class NoEditDelegate: public QStyledItemDelegate {
        public:
          NoEditDelegate(QObject* parent=0): QStyledItemDelegate(parent) {}
          virtual QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {
            return 0;
          }
        };
    

    稍后将其用作您的专栏的自定义委托

    ui->parameterView->setItemDelegateForColumn(0, new NoEditDelegate(this));
    

    【讨论】:

    • 不错的选择。您还可以将代理分配给整个视图,并通过检查index.column() 来检查它是否是被阻止的列。您还可以通过将 index.internalPointer() 重铸为 QTreeWidgetItem* 来获得对 QTreeWidgetItem 本身的访问权限,以便更好地控制何时阻止编辑,例如仅在项目有子项时阻止编辑(如我的情况)。
    • 很好的答案,一个小的微调,你可以使用这个委托给所有人: virtual QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (index.column() >0) { 返回 0; } return QStyledItemDelegate::createEditor(parent, option, index); }}
    【解决方案3】:

    看来您将不得不放弃使用QTreeWidgetQTreeWidgetItem 并使用QTreeViewQAbstractItemModel。 “Widget”类是更抽象但更灵活版本的具体实现的便利类。 QAbstractItemModel 有一个调用 flags(QModelIndex index),您可以在其中为您的列返回适当的值。

    【讨论】:

    • 不一定(如果我没记错的话)。请参阅下面的答案。
    • 这比下面发布的 NoEditDelegate 解决方案要多得多,我认为这是最好的。
    • 谢谢@David。我还赞成 NoEditDelegate 解决方案。它看起来更整洁、更完整,我会推荐它用于多个编辑触发器。
    【解决方案4】:

    似乎标准的 QTreeWidget 不允许这样做。我认为有两种方法可以做到这一点:

    1. 将 QTreeView 与您自己的从 QAbstractItemModel 派生的类一起使用并覆盖标志函数

    2. 将 QTreeView 与 QStandardItemModel 一起使用。然后,当您添加项目时,只需设置适当的列以允许编辑:

    这是第二个选项的一些代码:

    QString x, y;
    QList<QStandardItem*> newIt;
    QStandardItem * item = new QStandardItem(x);
    item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
    newIt.append(item);
    item = new QStandardItem(y);
    item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsEditable);
    newIt.append(item);
    model->appendRow(newIt);
    

    我发现第二种方法更简单,但这取决于您希望模型具有多大的灵活性。

    【讨论】:

      【解决方案5】:

      我发现最简单的方法是使用 Qt::ItemFlags

      void myClass::treeDoubleClickSlot(QTreeWidgetItem *item, int column)
      {
          Qt::ItemFlags tmp = item->flags();
          if (isEditable(item, column)) {
              item->setFlags(tmp | Qt::ItemIsEditable);
          } else if (tmp & Qt::ItemIsEditable) {
              item->setFlags(tmp ^ Qt::ItemIsEditable);
          }
      }
      

      if 的顶部通过OR 添加编辑功能,底部使用AND 检查是否存在,然后使用XOR 将其删除。

      这样,编辑功能在您需要时添加,在您不需要时删除。

      然后将此函数连接到树小部件的itemDoubleClicked() 信号,并在isEditable() 中写入您的“编辑或不编辑”决定

      【讨论】:

      • 完美回答我
      【解决方案6】:
      class EditorDelegate : public QItemDelegate
      {
          Q_OBJECT
      
      public:
          EditorDelegate(QObject *parent):QItemDelegate(parent){};
          QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
      };
      
      QWidget* EditorDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
      {
          if(index.column() == 1)
          {
              return QItemDelegate::createEditor(parent, option, index);
          }
          return nullptr;
      }
      

      QTreeWidget

      myQTreeWidget::myQTreeWidget()
      {
          EditorDelegate *d = new EditorDelegate(this);
          this->setItemDelegate(d);
      }
      

      【讨论】:

      • 两件事:如果不应编辑列,则从 createEditor() 返回 nullptr,可能作为 else 的一部分。并将应编辑的项目的项目标志设置为Qt::ItemIsEditable,否则将不会调用委托。
      【解决方案7】:

      可能有点晚了,但可能会有所帮助:

      void MyClass::on_treeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column) {
          Qt::ItemFlags flags = item->flags();
          if(column == 0)
          {
              item->setFlags(flags & (~Qt::ItemIsEditable));
          }
          else
          {
              item->setFlags(flags | Qt::ItemIsEditable);
          } 
      }
      

      这里的 0 是您要设为只读的列的索引。

      flags & (~Qt::ItemIsEditable)
      

      将 ItemIsEditable 位置设置为 0,而不管项目的前一个标志。

      flags | Qt::ItemIsEditable
      

      不管前面的标志,都将它设置为 1。

      【讨论】:

        【解决方案8】:

        我发现下面的代码可以很好地满足我的需要,并且确实“有点”停止了 用户编辑列的某些部分:

        我基本上先检查角色,然后再检查列。我只允许在第 0 列进行编辑。因此,如果用户在任何其他列中对其进行编辑,则我会停止 setData 编辑并且不会进行任何更改。

        void treeItemSubclassed::setData(int column, int role, const QVariant &value) {
            if (role == Qt::ItemIsEditable && column != 0){
                return;
            }
            QTreeWidgetItem::setData(column, role, value);
        }
        

        【讨论】:

          【解决方案9】:

          根据行和列设置树小部件的子级是否可编辑(树的节点数)。

          【讨论】:

          • 我该怎么做? QTreeWidgetItem::setFlags 不将列作为参数。我应该在QTreeWidget 中执行此操作,如果可以,使用哪种方法?
          【解决方案10】:

          我通常是 PySide 和 Python 的新手,但我能够通过向 QTreeWidget 注册 itemClicked 回调来使其工作。在回调中,检查列并仅在您希望允许编辑的列中调用“editItem”。

          class Foo(QtGui.QMainWindow):
          ...
          def itemClicked(self, item, column):
             if column > 0:
                self.qtree.editItem(item, column)
          

          通过不为第 0 列调用 editItem,该事件基本上被丢弃。

          【讨论】:

          • 现在尝试按 F2,您将能够编辑那些所谓的不可编辑的列 ;-)
          猜你喜欢
          • 2015-09-21
          • 2016-09-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-18
          • 2011-02-21
          • 1970-01-01
          相关资源
          最近更新 更多