Eventi attivati quando i widget vengono aggiornati a livello di codice

0

Nell'applicazione GUI su cui sto lavorando ho un numero di widget personalizzati (compositi) che ho creato, con ogni widget che ha una funzione update_gui in cui accedo al mio database SQLite in modo da poter compilare aree di testo , imposta lo stato della casella di controllo, ecc.

Mi imbatto costantemente nel problema degli eventi che vengono generati quando viene eseguito il codice gui_update , ad esempio quando aggiorno lo stato di una casella di controllo e viene attivato l'evento di modifica per la casella di spunta

Cosa posso fare per evitare questo problema? (O per aggirare il problema? Devo ripensare all'intero approccio?) Non voglio che il codice di gestione degli eventi venga eseguito quando lo stato della casella di controllo (o altro widget) viene aggiornato a livello di programmazione

Un approccio che ho provato è quello di gestire l'evento click o mousedown (o tastiera per il testo) e usarlo al posto dell'evento che viene attivato quando la casella di controllo cambia stato. Il problema con questo approccio è che potrebbero esserci altri modi per cambiare lo stato (ad esempio, navigare alla casella di controllo con la tastiera e premere space )

Attualmente sto lavorando con Qt (con i binding PyQt5) ma ho avuto lo stesso problema su un'altra piattaforma, quindi il problema sembra più generale, anche se forse la soluzione potrebbe essere specifica per Qt

Grato aiuto e cordiali saluti, Tord

    
posta sunyata 21.03.2017 - 22:22
fonte

2 risposte

0

Un'alternativa al suggerimento di ymoreau di usare QSignalBlocker è di impostare un flag all'interno del widget composito

Esempio di codice in Python:

class CompositeWidget(QtWidgets.QWidget):

    def __init__(self):
        super().__init__()
        self.gui_update_in_progress_bl = False

        self.widget_one = QtWidgets.QListWidget()
        self.widget_one.itemSelectionChanged.connect(
            self.on_widget_selection_changed)

    def on_widget_selection_changed(self):
        if self.gui_update_in_progress_bl:
            return

        # - writing to database/model here -

    def update_gui(self):
        self.gui_update_in_progress_bl = True

        # - update of widget_one here -

        self.gui_update_in_progress_bl = False

Questo dovrebbe funzionare anche in generale, penso, l'unica cosa di cui mi preoccupo è se il segnale che viene inviato quando widget_one viene aggiornato non viene elaborato subito, ma messo in coda (forse a causa del threading ) e invece viene elaborato dopo la fine del metodo update_gui . (Ma immagino che questo sia un caso di cui mi devo preoccupare solo se uso il multi-threading all'interno di Qt, per favore commentalo se ne sai di più!)

Un vantaggio con questo approccio è che posso scegliere da me quale dei gestori del segnale di uscire (ad esempio on_widget_selection_changed nell'esempio sopra)

    
risposta data 07.08.2017 - 18:49
fonte
1

Come detto nel commento, puoi utilizzare QSignalBlocker per impedire l'attivazione degli eventi.
Verso il basso: non c'è modo di scegliere cosa bloccare, nel caso abbiate bisogno di altri segnali dallo stesso oggetto.

A volte hai anche un segnale equivalente che non viene attivato quando il valore viene modificato a livello di codice. Come QLineEdit::textChanged (sempre attivato) e QLineEdit::textEdited (attivato solo da una modifica utente).
È meglio quando non hai il controllo sull'emettitore (quindi non puoi bloccare i segnali).

Infine, in base alla tua architettura puoi anche riempire tutti i tuoi widget durante l'inizializzazione della tua GUI e successivamente connettere i segnali alle slot.

Tuttavia, ad esempio se si dispone di un widget modulo che cambia a seconda del valore di un combobox, si desidera che la casella combinata emetta il segnale e configuri il widget del modulo, indipendentemente dal fatto che la modifica sia stata apportata dall'utente o dal programma.
Quindi credo che dovresti provare ad avere un modello di dati in grado di gestire tali modifiche programmatiche (controlla che il valore sia lo stesso del database e ignoralo ad esempio) e non blocchi i segnali . Perché se una parte del codice si basa su quei segnali in futuro, potresti finire con comportamenti strani non sempre facili da individuare.

    
risposta data 13.07.2017 - 14:03
fonte

Leggi altre domande sui tag