我々は、彼らがにドロップすることが可能なカテゴリの一覧と設定するためのフラグを付けて、辞書にsettings
すべてのカテゴリを定義します。たとえば:
default=QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEnabled
drag=QtCore.Qt.ItemIsDragEnabled
drop=QtCore.Qt.ItemIsDropEnabled
settings={
"family":(["root"],default|drag|drop),
"children":(["family"],default|drag)
}
カテゴリ「家族」のすべての項目は、ドラッグを受け取ることができ、かつ唯一の「ルート」(目に見えないルート項目)にドロップすることができます。 カテゴリ "子供"の各項目は、 "家族"にしかドロップできません。
ツリー
にツールチップ「カテゴリ」とQTreeWidgetItem(strings,parent)
を生成しsetting
におけるマッチングフラグaddItem(strings,category,parent=None)
方法アイテムを追加します。アイテムを返します。例:
dupont=ex.addItem(["Dupont"],"family")
robert=ex.addItem(["Robertsons"],"family")
ex.addItem(["Laura"],"children",dupont)
ex.addItem(["Matt"],"children",robert)
...
ドラッグ再実装と
self.currentItem()
と判定されたドラッグ中の項目(複数選択が処理されていない)ドロップ。このアイテムを削除できるカテゴリのリストはokList=self.settings[itemBeingDragged.data(0,role)][0]
です。
マウスの下のアイテム、「ドロップターゲット」は、self.itemAt(event.pos())
です。空白にマウスを置くと、ドロップターゲットはルートアイテムに設定されます。
dragMoveEvent
(降下は無視/受け入れられるかどうかについて視覚的な手がかり)
ドロップターゲットがokList
であれば、我々は定期的dragMoveEvent
を呼び出します。 そうでない場合は、「ドロップターゲットの隣に」チェックする必要があります。画像の下で、マウスの下の項目はRobertsonsですが、実際のドロップターゲットはルート項目です(Robertsonsの下の行を参照してください)。これを修正するには、アイテムをドロップターゲットの親にドラッグできることを確認します。そうでない場合はevent.ignore()
と呼びます。
残っている唯一の問題は、マウスが実際に「Robertsons」にあるときです:ドラッグイベントが受け入れられます。視覚的な合図は、それがそうでないときにドロップが受け入れられると言う。
dropEvent
代わりの「ターゲットをドロップする次」の、私たちは常にドロップを受け入れ、その後、ミスを修正するために非常にトリッキーでドロップを受け入れるか、無視します。
新しい親が古い親と同じ場合、またはそれがokList
にある場合、何もしません。それ以外の場合は、ドラッグされたアイテムを古い親に戻します。
は時々ドロップアイテムが崩壊されますが、これは簡単に二つの例を最後に
itemBeingDragged.setExpanded()
、完全なコードで固定することができます:あなたはそれができる言及 import sys
from PyQt4 import QtCore, QtGui
class CustomTreeWidget(QtGui.QTreeWidget):
def __init__(self,settings, parent=None):
QtGui.QTreeWidget.__init__(self, parent)
#self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
self.setItemsExpandable(True)
self.setAnimated(True)
self.setDragEnabled(True)
self.setDropIndicatorShown(True)
self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
self.settings=settings
root=self.invisibleRootItem()
root.setData(0,QtCore.Qt.ToolTipRole,"root")
def dragMoveEvent(self, event):
role=QtCore.Qt.ToolTipRole
itemToDropIn = self.itemAt(event.pos())
itemBeingDragged=self.currentItem()
okList=self.settings[itemBeingDragged.data(0,role)][0]
if itemToDropIn is None:
itemToDropIn=self.invisibleRootItem()
if itemToDropIn.data(0,role) in okList:
super(CustomTreeWidget, self).dragMoveEvent(event)
return
else:
# possible "next to drop target" case
parent=itemToDropIn.parent()
if parent is None:
parent=self.invisibleRootItem()
if parent.data(0,role) in okList:
super(CustomTreeWidget, self).dragMoveEvent(event)
return
event.ignore()
def dropEvent(self, event):
role=QtCore.Qt.ToolTipRole
#item being dragged
itemBeingDragged=self.currentItem()
okList=self.settings[itemBeingDragged.data(0,role)][0]
#parent before the drag
oldParent=itemBeingDragged.parent()
if oldParent is None:
oldParent=self.invisibleRootItem()
oldIndex=oldParent.indexOfChild(itemBeingDragged)
#accept any drop
super(CustomTreeWidget,self).dropEvent(event)
#look at where itemBeingDragged end up
newParent=itemBeingDragged.parent()
if newParent is None:
newParent=self.invisibleRootItem()
if newParent.data(0,role) in okList:
# drop was ok
return
else:
# drop was not ok, put back the item
newParent.removeChild(itemBeingDragged)
oldParent.insertChild(oldIndex,itemBeingDragged)
def addItem(self,strings,category,parent=None):
if category not in self.settings:
print("unknown categorie" +str(category))
return False
if parent is None:
parent=self.invisibleRootItem()
item=QtGui.QTreeWidgetItem(parent,strings)
item.setData(0,QtCore.Qt.ToolTipRole,category)
item.setExpanded(True)
item.setFlags(self.settings[category][1])
return item
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
default=QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEnabled|QtCore.Qt.ItemIsEditable
drag=QtCore.Qt.ItemIsDragEnabled
drop=QtCore.Qt.ItemIsDropEnabled
#family example
settings={
"family":(["root"],default|drag|drop),
"children":(["family"],default|drag)
}
ex = CustomTreeWidget(settings)
dupont=ex.addItem(["Dupont"],"family")
robert=ex.addItem(["Robertsons"],"family")
smith=ex.addItem(["Smith"],"family")
ex.addItem(["Laura"],"children",dupont)
ex.addItem(["Matt"],"children",dupont)
ex.addItem(["Kim"],"children",robert)
ex.addItem(["Stephanie"],"children",robert)
ex.addItem(["John"],"children",smith)
ex.show()
sys.exit(app.exec_())
#food example: issue with "in between"
settings={
"food":([],default|drop),
"allVegetable":(["food"],default|drag|drop),
"allFruit":(["food"],default|drag|drop),
"fruit":(["allFruit","fruit"],default|drag|drop),
"veggie":(["allVegetable","veggie"],default|drag|drop),
}
ex = CustomTreeWidget(settings)
top=ex.addItem(["Food"],"food")
fruits=ex.addItem(["Fruits"],"allFruit",top)
ex.addItem(["apple"],"fruit",fruits)
ex.addItem(["orange"],"fruit",fruits)
vegetable=ex.addItem(["Vegetables"],"allVegetable",top)
ex.addItem(["carrots"],"veggie",vegetable)
ex.addItem(["lettuce"],"veggie",vegetable)
ex.addItem(["leek"],"veggie",vegetable)
ex.show()
sys.exit(app.exec_())
setDataを使用して行います。それがどうやって行なわれるのかを教えてください。 – JokerMartini
@JokerMartini。この例ではバグを修正しましたが、全体的な解決策は非常に信頼できるとは思えません。 'setData'を使っても違いはありません。現時点では、私はもっと良いアイデアはなく、それ以上検討する時間はありません。 – ekhumoro
あなたは私の状況で私を助けることができるでしょうか?ここで私の投稿を更新しました。私はそれがほとんど動作しているが、それはいくつかのバグがありますhttp://stackoverflow.com/questions/34133789/controlling-drag-n-drop-disable-enable-of-qtreewidget-items-python?noredirect=1#comment56017728_34133789 – JokerMartini