3

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

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

我知道我可以忽略 dropMimeData 中的“插入”删除(我正在重新实现),通过检查行和列是否有效(删除到现有项目的行和列设置为 -1,父项设置为当前项目)和我正在这样做。但是,我不想得到这些滴。IE。我希望你总是在上面的项目或下面的项目上掉下来,而不是在项目之间。

有任何想法吗?

感谢您的任何建议,贾尔斯

4

3 回答 3

3

dragEnterEvent您需要通过在自定义视图中重新实现该方法来捕获拖动输入事件。Qt 文档中的示例是:

void Window::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasFormat("text/plain"))
        event->acceptProposedAction();
}

在您的情况下,您可能需要将事件中的 x 和 y 位置与最近的项目或类似的东西的 x 和 y 位置进行比较,并根据该信息拒绝或接受建议的操作。

QAbstractItemModel::dropMimeData文档中:

视图的责任是为应该插入数据的位置提供合适的位置。

我将其解释为,如果它不是底层模型(例如您的模型)支持的东西,则视图应该拒绝下降。

于 2011-08-05T04:21:50.323 回答
3

从 Qt 5.4 开始(我认为即使在 Qt 4.8 中也是如此),设置DragDropOverwriteModetrue正确地导致拖动只能放在现有项目上,并防止出现“高于/低于项目”放置目标。

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

然而,能够计算项目可以被丢弃的位置仍然很有用。例如在 QTreeView 中,不能将拖动的东西放在项目的左边距,即下面的红色区域:

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

于 2016-03-22T11:58:35.950 回答
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);
}
于 2020-10-04T22:27:38.280 回答