1

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

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

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

任何可能的解决方案?

4

1 回答 1

2

问题是由QTreeWidget's implementation 引起的。当项目在模型中移动时,它会删除旧位置的项目并在新位置重新创建它们。我们需要确保三件事:

  1. 当其项目被删除时,拯救嵌入的小部件不被删除。
  2. 将一些信息附加到项目,以便我们可以跟踪它们并选择哪个小部件属于某个项目。
  3. 移动项目后重新插入小部件。

这是概念验证的实现。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模式和用鼠标拖动项目对其进行了测试。也许在其他一些情况下,您需要收听其他模型的信号。

于 2014-08-31T00:28:40.257 回答