从 Qt 5.4 开始(我认为即使在 Qt 4.8 中也是如此),设置DragDropOverwriteMode
为true
将正确地导致拖动只能放在现有项目上,并防止出现“高于/低于项目”放置目标。
此外,与问题声称的不同,默认情况下DragDropOverwriteMode
设置false
为QTreeView
(我没有检查,可能是较新的 Qt 版本),因此需要true
手动设置。
然而,能够计算项目可以被丢弃的位置仍然很有用。例如在 QTreeView 中,不能将拖动的东西放在项目的左边距,即下面的红色区域:

如果在无效的红色区域中放置了某些东西,dropMimeData
则将调用parent
设置为 的参数NULL
。因此,提前向用户显示“你不能放在这里”光标ignore
会很有用,这样他们就知道他们不能放在那里。Qt 没有实现在拖动时在无效区域上更改鼠标光标(从 Qt 5.4 开始),但我们可以这样做:dragMoveEvent
bool SubclassedTreeView::dropResultsInValidIndex(const QPoint& pos)
{
QTreeWidgetItem* item = itemAt(pos);
if (item == NULL || !indexFromItem(item).isValid())
return false;
return visualRect(indexFromItem(item)).adjusted(-1, -1, 1, 1).contains(pos, false);
}
virtual void SubclassedTreeView::dragMoveEvent(QDragMoveEvent* event)
{
QTreeWidget::dragMoveEvent(event);
if (!event->isAccepted())
return;
if (dropResultsInValidIndex(event->pos()))
event->accept();
else
event->ignore(); //Show 'forbidden' cursor.
}
virtual bool SubclassedTreeView::dropMimeData(QTreeWidgetItem* parent, int index, const QMimeData* data, Qt::DropAction action)
{
Q_UNUSED(index);
//Modify the following action and data format checks to suit your needs:
if (parent == NULL || action != Qt::CopyAction || !data->hasFormat("my/preferred-type"))
return false;
QModelIndex modelIndex = indexFromItem(parent);
//modelIndex is where the data is dropped onto. Implement your custom drop action here...
return true;
}
上面的代码包含一小部分visualRect….adjusted(-1, -1, 1, 1)
是从QAbstractItemViewPrivate::position
源代码中窃取的。实际上这个函数的来源也可以用来计算item的覆盖/插入/无效QAbstractItemViewPrivate::position
区域false
。