Python QAction知道在QTableView中触发包含它的上下文菜单的项目
我有一个QTableView/QAbstractTableModel框架,我在其中实现了一个上下文菜单,最多有2个操作,这取决于请求菜单的索引。对于这两个操作中的一个,一旦触发,我希望在请求上下文菜单的位置发出索引。我有一个可行的解决方案,但我不喜欢 守则:Python QAction知道在QTableView中触发包含它的上下文菜单的项目,python,pyqt,Python,Pyqt,我有一个QTableView/QAbstractTableModel框架,我在其中实现了一个上下文菜单,最多有2个操作,这取决于请求菜单的索引。对于这两个操作中的一个,一旦触发,我希望在请求上下文菜单的位置发出索引。我有一个可行的解决方案,但我不喜欢 守则: class MyModel(QAbstractTableModel): ... def _restore_all(self): print('restore all') def _restore
class MyModel(QAbstractTableModel):
...
def _restore_all(self):
print('restore all')
def _restore_index(self, index):
print('restore index at: row = ' , index.row(), ', column = ', index.column())
...
class _ItemAwareAction(QAction):
_mytriggered = pyqtSignal('QModelIndex')
def __init__(self, *args, index=None, **kwargs):
super().__init__(*args, **kwargs)
self._index = index
self.triggered.connect(self._emit_index)
def _emit_index(self):
self._mytriggered.emit(self._index)
class MyTableView(QTableView):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setContextMenuPolicy(Qt.CustomContextMenu)
model = MyModel(self)
self.setModel(model)
# Attributes
restore_all_action = QAction('Restore all values', self)
self._restore_all_action = restore_all_action
self._menu = QMenu(self)
# Connexions
self.customContextMenuRequested.connect(self._item_context_menu)
restore_all_action.triggered.connect(model._restore_all)
def _item_context_menu(self, pos):
menu = self._menu
menu.clear()
index = self.indexAt(pos)
model = self.model()
originals = model._originals
if not originals:
return
menu.addAction(self._restore_all_action)
references = model._index_to_references(index)
if references in originals:
action = _ItemAwareAction(
'Restore this value', parent=self, index=index
)
action._mytriggered.connect(model._restore_index)
menu.addAction(action)
menu.popup(self.viewport().mapToGlobal(pos))
...
我发现我的
\u ItemAwareAction
类是一个不必要的循环。也许您可以给我指出一个更简单、更直接的解决方案。更简单的解决方案是使用lambda或partials:
def\u项目上下文菜单(self,pos):
# ...
如果参考文件为原件:
action=QAction('恢复此值',父级=self)
action.triggered.connect(lambda:model.\u restore\u index(索引))
# ...
由于您没有执行排序循环,您甚至可以只检查触发的操作是否应该重置,这是通过使用exec()
(在触发/关闭菜单之前阻止)而不是立即返回来完成的:
def\u项目上下文菜单(self,pos):
# ...
如果参考文件为原件:
restoreAction=QAction('Restore this value',parent=self)
其他:
#取消菜单不返回任何内容,我们需要与其他内容进行比较
restoreAction=-1
if menu.exec(self.viewport().mapToGlobal(pos))==恢复操作:
模型。还原索引(索引)
另一种选择是使用操作的,然后连接到菜单triggered
action
类MyTableView(QTableView):
定义初始化(self,*args,**kwargs):
# ...
self.\u菜单=QMenu(self)
自我菜单触发连接(自我菜单触发)
def_菜单_已触发(自身、动作):
如果isinstance(action.data(),QtCore.QModelIndex):
self.model().\u restore\u索引(action.data())
定义项目上下文菜单(自身、位置):
# ...
如果参考文件为原件:
action=QAction('恢复此值',父级=self)
action.setData(索引)
# ...
Use,它同步执行,并返回单击的操作(或无)。这样,索引在当前范围内仍然可用。或者执行action.triggered.connect(lambda:model.\u restore\u index(index))
。您好,非常感谢您的建议。我不太喜欢使用exec
执行匿名函数或同步执行。因此,我选择执行操作.setData(index)
,但我没有实现您的\u菜单\u触发的方法,而是从MyModel.\u restore\u index
方法中删除了index参数,只保留self
,要获取索引,我要执行index=self.sender().data()<代码> > @ J.Frango认为,“代码> Exc/<代码>只对来自CutExtMeCin事件的调用(这是触发<代码> CuutTraceMeNeURQuest<<代码>信号)的阻塞,但不会阻止主QT循环的事件处理(它实际上执行一个私有的QEventLoop,就像Q对话)一样;事实上,即使在Qt源中也很常见。还要注意,使用self.sender()
并不总是安全的(但是,至少在这个简单的场景中,只要不涉及线程,它应该是安全的)。@musicamente您完全正确,我没有意识到这一点,文档中已经明确说明了这一点,谢谢。