QTreeWidgetItem问题:使用setWidgetItem设置的项目在移动后是不相信的

时间:2014-08-28 22:51:23

标签: qt qtreewidget qtreewidgetitem

我有一堆QTreeWidgetItems,其中嵌入了小部件,我使用QTreeWidgetItem类中的setItemWidget()函数进行设置。

问题是我随时使用拖放或任何其他方式移动QTreeWidgetItem我之前设置的嵌入式窗口小部件消失。我在各种论坛上看到其他人也遇到过同样的问题(见下面的链接)

http://www.qtcentre.org/threads/40500-QTreeWidget-setItemWidget%28%29-item-disappears-after-moving-item

任何可能的解决方案?

1 个答案:

答案 0 :(得分:1)

问题是由QTreeWidget的实施引起的。当项目在模型中移动时,它会删除旧位置的项目并在新位置重新创建它们。我们需要确保3个细分:

  1. 挽救嵌入的小部件,使其在删除项目时被删除。
  2. 将一些信息附加到项目,以便我们可以跟踪它们并选择哪个小部件属于某个项目。
  3. 移动项目后重新插入小部件。
  4. 这是概念验证实现。 Tree_widget_keeper_wrapper确保第一个目标,setItemWidget重新实现确保第二个目标,rows_inserted广告位确保第三个目标。我测试它是否有效但在使用实际项目之前应该进行改进。 Qt::UserRole应更改为可配置的角色。我们应该使用模型本身未使用的角色。我将所有实现都放到类声明中以使其更具可读性,但您应该在实际代码中将它们分开。

    class Tree_widget_keeper_wrapper : public QWidget {
      Q_OBJECT
    public:
      Tree_widget_keeper_wrapper(QWidget* child) {
        _child = child;
        QVBoxLayout* layout1 = new QVBoxLayout(this);
        layout1->setContentsMargins(0, 0, 0, 0);
        layout1->addWidget(_child);
      }
    
      ~Tree_widget_keeper_wrapper() {
        if (_child->parent() == this) {
          _child->hide();
          _child->setParent(0);
        }
      }
    
    private:
      QWidget* _child;
    
    };
    
    class Fixed_tree_widget : public QTreeWidget {
      Q_OBJECT
    public:
      Fixed_tree_widget(QWidget* parent) : QTreeWidget(parent) {
        connect(model(), SIGNAL(rowsInserted(QModelIndex,int,int)),
                this, SLOT(rows_inserted(QModelIndex,int,int)));
      }
    
      void setItemWidget(QTreeWidgetItem* item, int column, QWidget* widget) {
        QTreeWidget::setItemWidget(item, column, new Tree_widget_keeper_wrapper(widget));
        item->setData(column, Qt::UserRole, all_widgets.count());
        all_widgets << widget;
      }
    
    private:
      QWidgetList all_widgets;
    
    private slots:
      void rows_inserted(QModelIndex parent, int start, int end) {
        for(int column = 0; column < model()->columnCount(parent); column++) {
          for(int row = start; row <= end; row++) {
            QModelIndex index = model()->index(row, column, parent);
            QVariant data = model()->data(index, Qt::UserRole);
            if (data.type() == QVariant::Int) {
              int i = data.toInt();
              QTreeWidgetItem* item = itemFromIndex(index);
              if (item && i >= 0 && i < all_widgets.count()) {
                setItemWidget(item, column, all_widgets[i]);
                all_widgets[i]->show();
              }
    
            }
          }
        }
      }
    
    };
    

    我针对InternalMove模式对其进行了测试,并使用鼠标拖动项目。也许在其他一些情况下,您需要听取其他模型的信号。