qt:QTreeView - 限制拖放仅发生在特定的祖父母(祖先)内
我有一个 QTreeView,其中实现了拖放以允许对项目重新排序。
给出以下树的示例:
Food <--fixed
|--Vegetables <--fixed
| |--carrots <-- draggable/parentable
| |--lettuce <-- draggable/parentable
| | |--icebergLettuce <-- draggable but NOT parentable
|--Fruit <-- fixed
| |--apple <-- draggable/parentable
| |--orange <-- draggable/parentable
| |--bloodOrange <-- draggable/parentable
etc...
任何标记为可拖动的东西都可以被拖动。任何标记为可作为父项的项目都可以有一个可拖动项目作为子项。任何标记为固定的东西都是固定的。
我的问题是,我将如何限制物品的掉落以留在特定的父母体内?例如,我可以拖动“bloodOrange”并使其成为“apple”或“orange”的子元素(或者甚至只是更改其在“Fruit”内的序数位置),但我不应该能够使其成为胡萝卜的子元素 我已经成功地为所有内容正确编码
了标志,除了限制放置操作保留在特定父级内的部分之外。我只是不知道如何捕获当前拖动的 QModelIndex (从中我可以确定父母、祖父母等)
谢谢!
这是我的 flags 方法的代码,以防有帮助: 注意:我将顶级子级称为节点(即“食物”),将下一级称为组(即“水果”),最后两个级别(即lettuce 和icebergLettuce)都是Params。
#---------------------------------------------------------------------------
def flags(self, index):
"""
Returns whether or not the current item is editable/selectable/etc.
"""
if not index.isValid():
return QtCore.Qt.ItemIsEnabled
#by default, you can't do anything
enabled = QtCore.Qt.NoItemFlags
selectable = QtCore.Qt.NoItemFlags
editable = QtCore.Qt.NoItemFlags
draggable = QtCore.Qt.NoItemFlags
droppable = QtCore.Qt.NoItemFlags
#get a pointer to the referenced object
item = index.internalPointer()
#only 'valid' cells may be manipulated ('valid' is defined by the obj)
if item.column_is_valid(index.column()):
#all valid cells are selectable and enabled
selectable = QtCore.Qt.ItemIsSelectable
enabled = QtCore.Qt.ItemIsEnabled
#column 0 cells may occasionally be dragged and dropped
if index.column() == 0:
#drag/drop is only possible if it is a param...
if item.get_obj_type() == 'param':
#...and then only child-less params may be dragged...
if item.get_child_count() == 0:
draggable = QtCore.Qt.ItemIsDragEnabled
#...and only params with a group as parent may be dropped on
if item.get_parent().get_obj_type() == "group":
droppable = QtCore.Qt.ItemIsDropEnabled
#all other valid columns > 0 may be edited (no drag or drop)
else:
editable = QtCore.Qt.ItemIsEditable
#return our flags.
return enabled | selectable| editable| draggable| droppable
I have a QTreeView in which I have implemented drag and drop to allow the re-ordering of items.
GIven the following example of a tree:
Food <--fixed
|--Vegetables <--fixed
| |--carrots <-- draggable/parentable
| |--lettuce <-- draggable/parentable
| | |--icebergLettuce <-- draggable but NOT parentable
|--Fruit <-- fixed
| |--apple <-- draggable/parentable
| |--orange <-- draggable/parentable
| |--bloodOrange <-- draggable/parentable
etc...
Anything marked as draggable may be dragged. Anything marked as parentable may have a draggable item as a child. Anything marked fixed is, well, fixed.
My question is, how would I go about limiting the dropping of an item to stay within a particular parent? For example, I could drag 'bloodOrange' and make it a child of 'apple' or 'orange' (or even just change its ordinal position inside of 'Fruit'), but I should not be able to make it a child of carrots or lettuce etc.
I've managed to correctly code the flags for everything except the part that limits a drop operation to stay within a particular parent. I just don't know how to capture the currently dragged QModelIndex (from which I can determine parent, grandparent, etc.)
Thanks!
Here is my code for the flags method in case it helps: Note: I refer to the top level children as Nodes (i.e. 'Food'), the next level as Groups (i.e. 'Fruit'), and the final two levels (i.e. lettuce and icebergLettuce) are both Params.
#---------------------------------------------------------------------------
def flags(self, index):
"""
Returns whether or not the current item is editable/selectable/etc.
"""
if not index.isValid():
return QtCore.Qt.ItemIsEnabled
#by default, you can't do anything
enabled = QtCore.Qt.NoItemFlags
selectable = QtCore.Qt.NoItemFlags
editable = QtCore.Qt.NoItemFlags
draggable = QtCore.Qt.NoItemFlags
droppable = QtCore.Qt.NoItemFlags
#get a pointer to the referenced object
item = index.internalPointer()
#only 'valid' cells may be manipulated ('valid' is defined by the obj)
if item.column_is_valid(index.column()):
#all valid cells are selectable and enabled
selectable = QtCore.Qt.ItemIsSelectable
enabled = QtCore.Qt.ItemIsEnabled
#column 0 cells may occasionally be dragged and dropped
if index.column() == 0:
#drag/drop is only possible if it is a param...
if item.get_obj_type() == 'param':
#...and then only child-less params may be dragged...
if item.get_child_count() == 0:
draggable = QtCore.Qt.ItemIsDragEnabled
#...and only params with a group as parent may be dropped on
if item.get_parent().get_obj_type() == "group":
droppable = QtCore.Qt.ItemIsDropEnabled
#all other valid columns > 0 may be edited (no drag or drop)
else:
editable = QtCore.Qt.ItemIsEditable
#return our flags.
return enabled | selectable| editable| draggable| droppable
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您希望拖动鼠标悬停在某些行上时显示“不允许”图标,我相信您无法从模型中做到这一点。您必须拦截视图wiedget 上的dragEnter/Move 事件。
但是,dropMimeData() 可以返回 False 来指示丢弃被拒绝。
请注意(在我的 Qt 版本中)qdnd_win 中存在关于模型拒绝的 drop 的错误。这是我基于一些源潜水的解决方法;这是在我的 QTreeView 子类上定义的方法:(
请注意,“并非无关紧要的工作”我的真正意思是“我不想费心拦截事件”:-)
If you want the drag to display the "not allowed" icon when hovering over certain rows, I believe you can't do it from the model. You'd have to intercept the dragEnter/Move events on the View wiedget.
However, dropMimeData() can return False to indicate that the drop is rejected.
Note that (in my Qt version) there is a bug in qdnd_win regarding drops that are rejected by the model. Here is my workaround based on some source diving; this is a method defined on my QTreeView subclass:
(note that by "not-insignificant work" I really mean "I don't want to bother intercepting the events" :-)