Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Qt QTreeView:仅允许在现有项上放置_C++_Qt_Qtreeview - Fatal编程技术网

C++ Qt QTreeView:仅允许在现有项上放置

C++ Qt QTreeView:仅允许在现有项上放置,c++,qt,qtreeview,C++,Qt,Qtreeview,我从QTreeView继承了一个自定义模型。我已启用拖放功能,当前可以将项目拖放到树上。但是,您当前可以拖放到现有项目或项目之间。我想限制这一点,以便您只能访问现有项目 我已经将DragDropOverwriteMode设置为true(实际上这是QTreeView的默认设置)。然而,这并不能阻止您在项目之间进行拖放,它只是意味着您也可以拖放到现有的项目上 我知道我可以通过检查行和列是否有效来忽略dropMimeData中的“插入”拖放(我正在重新实现),我正在这样做。然而,我宁愿不要这些药水。例

我从QTreeView继承了一个自定义模型。我已启用拖放功能,当前可以将项目拖放到树上。但是,您当前可以拖放到现有项目或项目之间。我想限制这一点,以便您只能访问现有项目

我已经将DragDropOverwriteMode设置为true(实际上这是QTreeView的默认设置)。然而,这并不能阻止您在项目之间进行拖放,它只是意味着您也可以拖放到现有的项目上

我知道我可以通过检查行和列是否有效来忽略dropMimeData中的“插入”拖放(我正在重新实现),我正在这样做。然而,我宁愿不要这些药水。例如,我希望你总是在上面的项目或下面的项目,而不是项目之间的下降

有什么想法吗

谢谢你的建议, Giles

您需要通过在自定义视图中重新实现
dragEnterEvent
方法来捕获drag-enter事件。Qt文档中的示例如下:

void Window::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasFormat("text/plain"))
        event->acceptProposedAction();
}
在您的情况下,您可能需要将事件中的x和y位置与最近项目或类似项目的x和y位置进行比较,并根据该信息拒绝或接受建议的操作

qabstractemmodel::dropMimeData
文档:

视图负责为数据插入的位置提供合适的位置

我将其解释为,如果它不是底层模型(如您的模型)支持的内容,则视图应该拒绝删除。

从Qt5.4开始(我假设即使在Qt4.8中也是如此),将
DragDropOverwriteMode
设置为
true
正确地导致只能在现有项目上拖放拖放,并防止出现“上/下项目”拖放目标

此外,与问题所声称的不同,
QTreeView
的默认情况下,
DragDropOverwriteMode
设置为
false
(我没有检查,可能是较新的Qt版本),因此需要手动将其设置为
true

但是,能够计算项目可以放置在什么位置仍然很有用。例如,在QTreeView中,不能将拖动的对象放置在项目的左边距上,即下面的红色区域:

如果在无效的红色区域中删除了某个内容,将调用
dropMimeData
,并将
父参数设置为
NULL
。因此,提前
忽略
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)
,它是从
QabstratemViewPrivate::position
源中偷来的。实际上,当
qabstracttemview private::position
也为
false
时,此函数的源可用于计算项目的覆盖/插入/无效区域。

我想根据下拉指示器的当前位置提出一个解决方案(
qabstracttemview::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);
}

谢谢你的回复和有用的信息。dragEnterEvent不适用,因为它仅在您第一次拖动小部件时调用,而不是在鼠标在小部件上移动时重复调用。但是,dragMoveEvent方法确实会被反复调用,所以我想我可以使用它。将moveEvent的rect与树中所有项的rect进行比较似乎过于复杂。有没有更简单的方法来确定我是否在一个项目上而不是在两个项目之间?我看过dropIndicatorPosition,它听起来应该做正确的事情。但是,无论我是在一个项目上还是在两个项目之间,它总是返回0。如果您有任何建议,我将不胜感激。我现在已经找到了一种更简单的方法,可以完全满足我的要求。仅当传递的索引有效时,才重新实现基础模型的flags方法以返回Qt::ItemIsProperted。在两个项目之间时,flags()被调用,索引无效,因此我可以决定不接受删除。很高兴您找到了它。现在我学到了一些关于我自己的模型和视图实现的知识。:)相反,您可以这样做:if(index.isValid()){return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled;}else{return Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDragEnabled;}这对我帮助很大:)!现在找到答案了。见对马特回答的评论。