我有一个从QTreeView继承的自定义模型。我已启用拖放功能,并且当前可以将项目拖放到树上。但是,您当前可以放入现有项目或项目之间。我想限制这一点,以便您只能删除现有项目。
我已将DragDropOverwriteMode设置为true(实际上这是QTreeView的默认值)。但是,这并不能阻止您在项目之间删除 - 这只意味着您也可以放弃现有项目。
我知道我可以通过检查行和列是否有效来忽略dropMimeData中的“插入”删除(删除现有项目的行和列设置为-1,父设置为当前项目),我这样做。但是,我不希望得到这些滴剂。 IE浏览器。我希望它能让你总是掉到上面的项目或下面的项目,从不在项目之间。
有什么想法吗?
感谢您的任何建议, 贾尔斯
答案 0 :(得分:3)
您需要通过在自定义视图中重新实现dragEnterEvent
方法来捕获拖动输入事件。 Qt文档中的示例是:
void Window::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat("text/plain"))
event->acceptProposedAction();
}
在您的情况下,您可能需要将事件中的x和y位置与最近项目的x和y位置或类似物进行比较,并根据该信息拒绝或接受建议的操作。
来自QAbstractItemModel::dropMimeData
文档:
视图有责任为应插入数据的位置提供合适的位置。
我已经解释为,如果不是基础模型支持的视图,视图应该拒绝掉落,例如你的。
答案 1 :(得分:2)
从Qt 5.4开始(我认为即使在Qt 4.8中也是如此),将DragDropOverwriteMode
设置为true
将正确会导致拖动仅在现有的情况下可以删除项目并防止出现“上方/下方项目”放置目标。
此外,与问题所声称的不同,DragDropOverwriteMode
默认设置为false
QTreeView
(我没有检查,也许是较新的Qt版本),所以它需要手动设置为true
。
然而,能够计算物品可以放置的位置仍然是有用的。例如,在QTreeView中,不能在项目的左边缘放置拖动的东西,即下面的红色区域:
如果在无效的红色区域中删除了某些内容,则会在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
时,此函数的来源可用于计算项目的覆盖/插入/无效区域。
答案 2 :(得分:0)
我想根据下降指示器(QAbstractItemView::DropIndicatorPosition
)的当前位置提出一个解决方案。它的实现非常简单,但不幸的是,要求显示放置指示器。但是,在某些情况下这可能是可以接受的。
TreeView::TreeView(QWidget* parent) : QTreeView(parent)
{
setDropIndicatorShown(true);
}
void TreeView::dragMoveEvent(QDragMoveEvent* event)
{
QTreeView::dragMoveEvent(event);
if (dropIndicatorPosition() != QTreeView::OnItem)
event->setDropAction(Qt::IgnoreAction);
}