2014-08-28 10 views
0

У меня есть куча QTreeWidgetItems, у которых есть встроенные в них виджеты, которые я установил с помощью функции setItemWidget() в классе QTreeWidgetItem.Проблема QTreeWidgetItem: элементы, установленные с помощью setWidgetItem, освобождаются после перемещения

Проблема заключается в том, что я перемещаю QTreeWidgetItem с помощью перетаскивания или любых других средств, которые встроенный виджет, который я установил до исчезновения. Я видел вокруг различных форумах, что другие имели такую ​​же проблему (см ссылку ниже)

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

Любые возможные решения?

ответ

1

Проблема связана с реализацией QTreeWidget. Когда элементы перемещаются внутри модели, они удаляют элементы в старых позициях и воссоздают их на новых позициях. Мы должны обеспечить 3 тонких слоя:

  1. Спасательный встроенный виджет от удаления при удалении его элемента.
  2. Прикрепите некоторую информацию к элементам, чтобы мы могли отслеживать их и выбирать, какой виджет принадлежит элементу.
  3. Вставить виджет после перемещения элемента.

Реализация концепции доказательств. Tree_widget_keeper_wrapper обеспечивает 1-ую цель, setItemWidget обеспечивает повторное выполнение второго, а слот rows_inserted обеспечивает 3-й. Я тестировал, что он работает, но его следует улучшить перед использованием в реальных проектах. 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 и перетаскиванием элементов с помощью мыши. Возможно, в некоторых других случаях вам нужно будет слушать сигналы другой модели.