从 Qt 5.4 开始(我认为即使在 Qt 4.8 中也是如此),将 DragDropOverwriteMode 设置为 true 将正确导致拖动只能放在现有项目上并防止“高于/低于项目”放置目标不再出现。
另外,与问题所声称的不同,DragDropOverwriteMode 默认设置为false QTreeView(我没有检查,可能是较新的 Qt 版本),因此需要将其设置为 true手动。
但是,能够计算出可以丢弃物品的位置仍然很有用。例如在QTreeView中,不能将拖拽的东西放到item的左边距,即下面的红色区域:
如果在无效的红色区域中放置了某些东西,则将调用 dropMimeData,并将 parent 参数设置为 NULL。因此,提前ignore 和dragMoveEvent 向用户向用户显示“你不能放在这里”光标会很有用,这样他们就知道他们不能放在那里。 Qt 没有实现在拖动时在无效区域上更改鼠标光标(从 Qt 5.4 开始),但我们可以这样做:
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 来源窃取的。其实当QAbstractItemViewPrivate::position也是false时,这个函数的来源可以用来计算item的覆盖/插入/无效区域。