2011-08-04 48 views
3

我有一個從QTreeView繼承的自定義模型。我已經啓用了拖放操作,並且可以將一個項目拖放到樹上。但是,您現在可以放入現有項目或項目之間。我想限制這個,這樣你只能放到現有的物品上。Qt QTreeView:只允許放在現有項目上

我已經將DragDropOverwriteMode設置爲true(實際上這是QTreeView的默認值)。然而,這並不能阻止你在物品之間掉落 - 這隻意味着你也可以放到現有的物品上。我知道我可以通過檢查行和列是否有效(drop into existing items have row and column set to -1 and parent set to the)來忽略dropMimeData中的「insert」drop(我正在重新實現)目前的項目),我正在這樣做。不過,我寧願不要獲得這些滴。 IE瀏覽器。我喜歡它,所以你總是會掉在上面的物品或下面的物品上,而不是在物品之間。

任何想法?

感謝您的任何建議, 賈爾斯

+0

現在找到答案。請參閱Matt的回答評論。 – giles123

回答

3

你「」需要捕獲的阻力在您的自定義視圖重新實現dragEnterEvent方法進入事件。從Qt的文檔的例子是:

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

在你的情況,你可能會需要比較在x和最接近的項目的y位置或者類似事件的X和Y位置,並拒絕或接受建議的行動基於這些信息。

QAbstractItemModel::dropMimeData文檔:

它是視圖,以提供該數據應插入的一個合適的位置的責任。

我認爲這意味着如果視圖不是基礎模型(如您的)支持的視圖,應該拒絕該視圖。

+1

感謝您的回覆和有用的信息。 dragEnterEvent並不合適,因爲只有當您第一次拖動小部件時纔會調用它,而不是在鼠標移過小部件時不重複。但是,dragMoveEvent方法不會重複調用,所以我認爲我可以使用它。 – giles123

+0

將moveEvent的矩形與樹中所有項的矩形進行比較似乎過於複雜了。有沒有更容易的方法來確定我是否在項目之上而不是在項目之間?我看過dropIndicatorPosition這聽起來應該是正確的。但是,無論我是否在項目之間或項目之間,它總是返回0。任何建議,將不勝感激。 – giles123

+2

我發現了一個更簡單的方法,它正是我想要的。重新實現基礎模型的標誌方法,只有當傳遞索引有效時才返回Qt :: ItemIsDropEnabled。當在兩個項目之間時,flags()會被調用一個無效的索引,所以我可以決定不接受這個drop。 – giles123

2

作爲Qt的5.4的(我假定這是真實的,即使在Qt的4.8),設置DragDropOverwriteModetrue正確使拖動是可投放僅在現有項,並防止「上方/下方項目」放置目標從出現。

而且,不像什麼的問題索賠,DragDropOverwriteMode默認情況下爲QTreeView設置爲false(我沒有檢查,也許是新的Qt版本),所以它需要手動設置爲true

但是,能夠計算物品可丟棄的位置仍然很有用。例如,在QTreeView則,一個不能落個拖事情上的項目的左邊距,即低於紅色區域:

QTreeView invalid drop areas

如果事情是無效的紅色區域下降,dropMimeData將有一個名爲參數設置爲NULL。因此,ignoredragMoveEvent提前顯示'你不能放在這裏'光標到用戶將是有用的,所以他們知道他們不能放在那裏。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::positionfalse時,此功能的來源也可用於計算該項目的覆蓋/插入/無效區域。