Проблема связана с реализацией QTreeWidget
. Когда элементы перемещаются внутри модели, они удаляют элементы в старых позициях и воссоздают их на новых позициях. Мы должны обеспечить 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
и перетаскиванием элементов с помощью мыши. Возможно, в некоторых других случаях вам нужно будет слушать сигналы другой модели.