[英]Qt QTreeView: Only allow to drop on an existing item
我有一個從 QTreeView 繼承的自定義模型。 我已啟用拖放功能,目前可以將項目拖放到樹上。 但是,您當前可以放置在現有項目上或項目之間。 我想限制這一點,以便您只能放下現有項目。
我已將 DragDropOverwriteMode 設置為 true(實際上這是 QTreeView 的默認設置)。 但是,這並不能阻止您在物品之間掉落 - 這只是意味着您也可以掉落到現有物品上。
我知道我可以忽略 dropMimeData(我正在重新實現)中的“插入”刪除,通過檢查行和列是否有效(刪除到現有項目的行和列設置為 -1,父項設置為當前項目)和我正在這樣做。 但是,我不想得到這些滴。 IE。 我希望你總是從上面的項目或下面的項目上掉下來,而不是在項目之間。
有任何想法嗎?
感謝您的任何建議,吉爾斯
從 Qt 5.4 開始(我認為即使在 Qt 4.8 中也是如此),將DragDropOverwriteMode
設置為true
將正確地導致拖動只能在現有項目上放置,並防止出現“項目上方/下方”放置目標。
此外,與問題所聲稱的不同,默認情況下, QTreeView
DragDropOverwriteMode
設置為false
(我沒有檢查,可能是較新的 Qt 版本),因此需要手動將其設置為true
。
然而,能夠計算物品可以被丟棄的位置仍然很有用。 例如在QTreeView中,不能在items的左邊距放置拖拽的東西,即下面的紅色區域:
如果在無效的紅色區域中dropMimeData
則將調用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
時,此函數的來源也可用於計算項目的覆蓋/插入/無效區域。
您需要通過在自定義視圖中重新實現dragEnterEvent
方法來捕獲拖動輸入事件。 Qt 文檔中的示例是:
void Window::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat("text/plain"))
event->acceptProposedAction();
}
在您的情況下,您可能需要將事件中的 x 和 y 位置與最近項目的 x 和 y 位置或類似的東西進行比較,然后根據該信息拒絕或接受建議的操作。
從QAbstractItemModel::dropMimeData
文檔:
視圖有責任為應插入數據的位置提供合適的位置。
我已經解釋為,如果它不是由基礎模型(例如您的模型)支持的內容,則視圖應該拒絕刪除。
我想根據放置指示器的當前位置 ( 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);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.