QTreeView - как узнать, является ли событие перетаскивания перестановкой или перемещением между родителями?

У меня есть подклассы QTreeView а также QAbstractItemModel и в настоящее время я использую drag-drop для перемещения элементов из одного родительского индекса в другой. Я хочу также добавить возможность изменить порядок элементов в пределах того же родительского индекса. Когда пользователь отбрасывает элемент между двумя другими элементами, мне нужно определить, должно ли быть перетаскивание между ними. Я также хотел бы нарисовать темную линию между двумя элементами при перемещении мыши, чтобы намекнуть, что произойдет, подобно многим другим представлениям древовидного типа (например, файловым обозревателям в большинстве операционных систем), как на прилагаемых рисунках:

Перетащите в существующий элемент:

перетащить в

Вставьте между двумя существующими элементами:

перетащить между

Автоматизирует ли Qt эту часть поведения перетаскивания, или мне нужно вручную вычислять положение мыши относительно края элемента дерева? Кроме того, как я могу нарисовать временную линию между двумя элементами в QTreeView?

1 ответ

Решение

Я сделал почти то же самое некоторое время назад, и я могу думать о 3 вещах:

  • вам придется переопределить ваш dropEvent()и, возможно, ваш dragMoveEvent();
  • чтобы проверить, куда вы сбрасываете элемент, используйте dropIndicatorPosition ();
  • чтобы показать индикатор падения, используйте setDropIndicatorShown (bool).

Вот очень минимальный пример того, что я делал.

в dragMoveEvent()Я показывал индикатор падения. Таким образом, при перетаскивании объекта всегда будет отображаться индикатор падения.

void MyTreeView::dragMoveEvent(QDragMoveEvent* event)
{
    setDropIndicatorShown(true);
    QTreeView::dragMoveEvent(event);
}

в dropEvent()Я управлял каждым делом, то есть был ли элемент, который я перетаскивал, другим элементом, над ним, под ним или в окне просмотра. Затем, в соответствии с этим, я управлял собственным падением, а в конце события я скрывал индикатор сброса.

void MyTreeView::dropEvent(QDropEvent* event)
{
    bool dropOK = false;
    DropIndicatorPosition dropIndicator = dropIndicatorPosition();

    switch (dropIndicator)
    {
    case QAbstractItemView::AboveItem:
        dropOK = true;
        break;
    case QAbstractItemView::BelowItem:
        dropOK = true;
        break;
    case QAbstractItemView::OnItem:
        dropOK = false;
        break;
    case QAbstractItemView::OnViewport:
        dropOK = false;
        break;
    }
    if(dropOK)
    {
        // Here, you need to manage yourself the case of dropping an item
    }
    setDropIndicatorShown(false); // hide the drop indicator once the drop is done
}

"Бонус": вы можете получить доступ к индикатору выпадения в своем собственном стиле с помощью PrimitiveElement PE_IndicatorItemViewItemDrop, Вы можете увидеть, как настроить его здесь и здесь.

Другие вопросы по тегам