我正在尝试将树的选择限制为特定列。
我正在大量使用代理来创建每列每个项目的自定义行为,编辑器等。我希望我能通过阻止事件或类似事件以某种方式从委托中做到这一点。问题是,我认为我必须创建一个模仿扩展选择的完全自定义解决方案。
然而,经过大量搜索和很少的示例,听起来我想在树视图上使用自定义QItemSelectionModel。这个假设是否正确?
如何创建将使用扩展选择模式的自定义QItemSelectionModel,但如果不在特定列中,则允许我忽略或还原选择。换句话说,单击另一列不应更改选择(不应选择或取消选择)
我知道如何添加选择模型。我要求帮助实现派生类(除非可以使用连接信号完成)。
我正在使用Python,但会重视任何帮助。
谢谢,
[编辑:]我发现了类似的问题: http://lists.qt.nokia.com/pipermail/qt-interest/2010-September/027647.html
“子类QItemSelectionModel并重新实现两个select方法 你想要的行为。只需忽略列>的范围部分。 0。 ... 或者只是重新实现flags()以使项目不可选。我不 知道这是否会产生任何副作用。“
我尝试在我的QTreeWidgetItem上重新实现标志,但它从未被调用过:
def flags(self, index):
print index.column()
return super(DDOutlinerBaseItem, self).flags(index)
答案 0 :(得分:4)
理论上,以下调整应该有效。
上述解决方案可以使用两个单独的方法和@pyqtSlot装饰器来消除重载方法名称的歧义:
@pyqtSlot(QModelIndex, QItemSelectionModel.SelectionFlags)
def select(self, index, command):
# ...
@pyqtSlot(QItemSelection, QItemSelectionModel.SelectionFlags)
def select(self, selection, command):
#...
这避免了在方法实现中检查某些类的实例的需要。
答案 1 :(得分:0)
第一个有趣的事情是,由于Python不能重载方法,我的select方法似乎只是被调用两次,对于参数0中的每个类型一次。这是一个例子来说明这个以及基本设置。我的QTreeWidget树名为'tree'(self.tree
)
# in __init__ of my QTreeWidget:
sel_model = ColumnSelectionModel(self.tree.model())
self.tree.setSelectionModel(sel_model)
class ColumnSelectionModel(QtGui.QItemSelectionModel):
def select(self, selection, selectionFlags):
"""
Runs both QItemSelectionModel.select methods::
1. select(QtCore.QModelIndex, QItemSelectionModel.SelectionFlags)
2. select(QtGui.QItemSelection, QItemSelectionModel.SelectionFlags)
The first seems to run on mouse down and mouse up.
The second seems to run on mouse down, up and drag
"""
print("select(%s, %s)" % (type(selection), type(selectionFlags)))
if isinstance(selection, QtGui.QItemSelection):
infos = []
for index in selection.indexes():
infos.append(("index=%s row=%s column=%s"
% (index, index.row(), index.column())))
print ", ".join(infos)
elif isinstance(selection, QtCore.QModelIndex):
index = selection
print("index=%s row=%s column=%s" % (index, index.row(), index.column()))
else:
raise Exception("Unexpected type for arg 0: '%s'" % type(selection))
super(ColumnSelectionModel, self).select(selection, selectionFlags)
这似乎解决了我的问题:
class ColumnSelectionModel(QtGui.QItemSelectionModel):
def __init__(self, model):
super(ColumnSelectionModel, self).__init__(model)
self.selectable_columns = [0]
""" Set the columns that are allowed to be selected """
def select(self, selection, selectionFlags):
"""
Ignores any selection changes if an item is not in one of the columns
in the self.selectable_columns list.
Is run by both QItemSelectionModel.select methods::
1. select(QtCore.QModelIndex, QItemSelectionModel.SelectionFlags)
2. select(QtGui.QItemSelection, QItemSelectionModel.SelectionFlags)
The first seems to run on mouse down and mouse up.
The second seems to run on mouse down, up and drag
"""
if isinstance(selection, QtGui.QItemSelection):
# This is the overload with the QItemSelection passed to arg 0
# Loop over all the items and if any are not in selectable_columns
# ignore this event. This works because it is run for every change
# so the offending selection index will always be the newest
indexes = selection.indexes()
for i in xrange(len(indexes)):
index = indexes[i]
if not index.column() in self.selectable_columns:
return
elif isinstance(selection, QtCore.QModelIndex):
# This is the overload with the QModelIndex passed to arg 0
# If this index isn't in selectable_columns, just ignore this event
index = selection
if not index.column() in self.selectable_columns:
return
else: # Just in case
raise Exception("Unexpected type for arg 0: '%s'" % type(selection))
# Fall through. Select as normal
super(ColumnSelectionModel, self).select(selection, selectionFlags)
在我的最终实现中,我计划将决策委托给我的委托系统,使其成为通用的,理论上能够动态地忽略我想要的任何索引。