(я начал с ответа Энди, спасибо Энди!)
1) aboutToHide () работает, повторно открывая меню в кэшированной позиции, НО также может войти в бесконечный цикл. Тестирование, если щелкнуть мышью за пределами меню, чтобы игнорировать повторное открытие, должно помочь.
2) Я пробовал фильтр событий, но он блокирует фактический щелчок по пункту меню.
3) Используйте оба.
Вот грязный шаблон, доказывающий, что он работает. Это сохраняет меню открытым, когда пользователь нажимает клавишу CTRL при нажатии:
# in __init__ ...
self.options_button.installEventFilter(self)
self.options_menu.installEventFilter(self)
self.options_menu.aboutToHide.connect(self.onAboutToHideOptionsMenu)
self.__options_menu_pos_cache = None
self.__options_menu_open = False
def onAboutToHideOptionsMenu(self):
if self.__options_menu_open: # Option + avoid an infinite loop
self.__options_menu_open = False # Turn it off to "reset"
self.options_menu.popup(self.__options_menu_pos_cache)
def eventFilter(self, obj, event):
if event.type() == QtCore.QEvent.MouseButtonRelease:
if obj is self.options_menu:
if event.modifiers() == QtCore.Qt.ControlModifier:
self.__options_menu_open = True
return False
self.__options_menu_pos_cache = event.globalPos()
self.options_menu.popup(event.globalPos())
return True
return False
Я говорю, что это грязно, потому что виджет здесь действует как фильтр событий как для кнопки, которая открывает меню, так и для самого меню. Использовать явные классы фильтра событий было бы достаточно просто добавить, и было бы немного легче следить за ними.
Возможно, bools можно заменить на проверку, находится ли мышь над меню, и если нет, не открывайте ее. Тем не менее, клавиша CTRL все еще должна быть учтена в моем случае использования, так что, вероятно, это не слишком хорошее решение, как есть.
Когда пользователь удерживает нажатой клавишу CTRL и щелкает меню, он щелкает переключателем, поэтому меню снова открывается, когда оно пытается закрыть. Позиция кэшируется, поэтому она открывается в той же позиции. Есть быстрое мерцание, но он чувствует себя нормально, так как пользователь знает, что он удерживает клавишу, чтобы сделать эту работу.
В конце дня (буквально) у меня уже было все меню, делающее правильные вещи. Я просто хотел добавить эту функциональность, и я определенно не хотел переходить на использование виджета только для этого. По этой причине я пока держу даже этот грязный патч.