Из документации о сигнале customContextMenuRequested(pos)
:
Позиция pos - это позиция события контекстного меню, которое получает виджет
Это означает, что вы всегда будете получать позицию мыши относительно виджета, который запускает сигнал .
Вы используете QWidget.childAt()
, что относительно родительской геометрии, но так как предоставленная позиция относительно дочернего виджета, вы всегда будете иметь координаты, относящиеся к верхнему левому углу родительского элемента.
Это становится понятным, если вы попытаетесь установить геометрию первого виджет в позиции, которая не находится в верхнем левом углу: даже если вы щелкните правой кнопкой мыши первый виджет, вы увидите, что меню не появится там, где вы щелкнули. Если вы присмотритесь, вы также увидите, что меню отображается точно в той позиции, по которой вы щелкнули, основываясь на координатах верхнего левого угла родительского элемента.
Для простоты простым решением было бы сопоставьте координаты от "sender
" (который является объектом, который сгенерировал последний сигнал, полученный приемником) его родителю:
def customMenuEvent(self, eventPosition):
child = self.childAt(self.sender().mapTo(self, eventPosition))
contextMenu = QMenu(self)
getText = contextMenu.addAction("Text")
getName = contextMenu.addAction("Name")
quitAct = contextMenu.addAction("Quit")
# note that the mapToGlobal is referred to the child!
action = contextMenu.exec_(child.mapToGlobal(eventPosition))
# ...
Но учтите, что это может приводить к некоторой несогласованности, особенно при работе с многопоточностью (поскольку теоретически другой поток мог запустить другой сигнал между событием щелчка правой кнопкой мыши и в момент, когда получатель фактически его получил).
Существуют различные подходы, позволяющие избежать этого, но ИТ в основном зависят от того, как вы собираетесь структурировать свою программу.
Например, вы можете использовать лямбда-выражение для добавления аргумента, который помогает идентифицировать источник, из которого было отправлено событие:
self.firstLabel.customContextMenuRequested.connect(
lambda pos, child=self.firstLabel: self.customMenuEvent(pos, child))
# ...
def customMenuEvent(self, eventPosition, child):
# ...