(ho iniziato con la risposta di Andy, quindi grazie Andy!)
1) aboutToHide() funziona, da ri-popping menu in una posizione memorizzata nella cache, ma può anche entrare in un ciclo infinito. Testare se il mouse viene cliccato fuori dal menu per ignorare la riapertura dovrebbe fare il trucco.
2) Ho provato un filtro eventi ma blocca il clic effettivo sulla voce di menu.
3) Utilizzare entrambi.
Ecco uno schema sporco per dimostrare che funziona. Ciò mantiene l'aperta menu quando l'utente tiene premuto il tasto CTRL quando si fa clic:
# 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
dico che è sporca perché il widget qui agisce come un filtro eventi sia per il pulsante che apre il menu così come il menu stesso . Usare classi di filtro eventi esplicite sarebbe abbastanza semplice da aggiungere e renderebbe le cose un po 'più facili da seguire.
È probabile che i bool vengano sostituiti con un segno di spunta per verificare se il mouse si trova sopra il menu e, in caso contrario, non aprirlo. Tuttavia, il tasto CTRL deve ancora essere preso in considerazione per il mio caso d'uso, quindi probabilmente non è lontano da una soluzione così semplice.
Quando l'utente tiene premuto CTRL e fa clic sul menu, capovolge un interruttore in modo che il menu si apra di nuovo quando tenta di chiudere. La posizione viene memorizzata nella cache in modo che si apra nella stessa posizione. C'è uno sfarfallio veloce, ma ci si sente bene poiché l'utente sa che stanno tenendo premuto un tasto per farlo funzionare.
Alla fine della giornata (letteralmente) ho già avuto l'intero menu facendo la cosa giusta. Volevo solo aggiungere questa funzionalità e sicuramente non volevo passare all'utilizzo di un widget solo per questo. Per questo motivo, sto mantenendo anche questa patch sporca per ora.
Grazie mille. Con lo stile plastico c'è davvero un margine da aggiungere. Così ho inserito la casella di controllo in un widget con un layout e impostato i margini (forse c'è un modo più semplice ...) Un'ultima cosa: la casella di controllo non si espande per tutta la larghezza del menu, quindi se il clic si verifica dopo la fine dell'etichetta della scatola, il menu è chiuso e la casella non è selezionata. L'impostazione della politica delle dimensioni non ha alcun effetto. – gregseth
Questo non funziona con 'QsystemTrayIcon.contextMenu()' su Ubuntu Unity come Unity non mostra Widget dall'interno di 'QWidgetAction' – Germar
@gregseth c'è un modo per espandere la casella di controllo alla larghezza completa del menu? – bob