Domanda

wx (e wxPython) ha due eventi che mi mancano in PyQt:

  • EVT_IDLE che viene inviato a un frame. Può essere utilizzato per aggiornare i vari widget in base allo stato dell'applicazione
  • EVT_UPDATE_UI che viene inviato a un widget quando deve essere ridipinto e aggiornato, quindi posso calcolarne lo stato nel gestore

Ora PyQt non sembra possederli e il libro PyQt suggerisce di scrivere un metodo updateUi e chiamarlo manualmente. Ho anche finito per chiamarlo da un timer una volta ogni 0,1 secondi, al fine di evitare molte chiamate manuali da metodi che potrebbero aggiornare la GUI. Mi sto perdendo qualcosa? C'è un modo migliore per raggiungere questo obiettivo?


Un esempio: ho una semplice app con un pulsante Start che avvia l'elaborazione. Il pulsante di avvio deve essere abilitato solo quando un file è stato aperto utilizzando il menu. Inoltre, sulla barra di stato è presente un widget permanente che visualizza informazioni.

La mia applicazione ha gli stati:

  1. Prima dell'apertura del file (in questo stato la barra di stato mostra qualcosa di speciale e il pulsante di avvio è disabilitato)
  2. Il file è stato aperto e l'elaborazione non è stata avviata: il pulsante di avvio è abilitato, la barra di stato mostra qualcos'altro
  3. L'elaborazione è in esecuzione: il pulsante di avvio ora dice " Stop " ;, e la barra di stato riporta l'avanzamento

In Wx, l'evento UI di aggiornamento del pulsante gestirà il suo stato: il testo su di esso e se è abilitato, a seconda dello stato dell'applicazione. Lo stesso per la barra di stato (o userei EVT_IDLE per quello).

In Qt, devo aggiornare il pulsante in diversi metodi che possono influenzare lo stato, o semplicemente creare un metodo update_ui e chiamarlo periodicamente in un timer. Qual è il modo più "QT" -ish?

È stato utile?

Soluzione

L'uso di EVT_UPDATE_UI in wxWidgets sembra evidenziare una delle differenze fondamentali nel modo in cui wxWidgets e Qt si aspettano che gli sviluppatori gestiscano gli eventi nel loro codice.

Con Qt, si collegano segnali e slot tra i widget nell'interfaccia utente, gestendo "la logica aziendale" in ogni slot o delegandolo a un metodo dedicato. In genere non ti preoccupare di apportare modifiche separate a ciascun widget nella tua GUI perché eventuali richieste di ridipingere verranno inserite nella coda degli eventi e consegnate quando il controllo ritorna al ciclo degli eventi. Alcuni eventi di pittura possono anche essere uniti per motivi di efficienza.

Quindi, in una normale applicazione Qt in cui segnali e slot vengono utilizzati per gestire i cambiamenti di stato, non è praticamente necessario disporre di un meccanismo inattivo che monitora lo stato dell'applicazione e aggiorna i widget poiché tali aggiornamenti dovrebbero avvenire automaticamente.

Dovresti dire qualcosa in più su ciò che stai facendo per spiegare perché hai bisogno di un equivalente a questo evento in Qt.

Altri suggerimenti

Manderei segnali Qt per indicare i cambiamenti di stato (ad esempio fileOpened, processingStarted, processingDone). Gli slot negli oggetti che gestiscono il pulsante Start e il widget della barra di stato (o sottoclassi) possono essere collegati a questi segnali, piuttosto che "polling" per lo stato corrente in un evento inattivo.

Se vuoi che il segnale venga rinviato più avanti nel loop degli eventi piuttosto che immediatamente (ad es. perché ci vorrà un po 'di tempo per fare qualcosa), puoi usare un "quotata in coda" connessione segnale-slot piuttosto che normale.

http://doc.trolltech.com/4.5/signalsandslots.html#signals

Il tipo di connessione è un parametro facoltativo per la funzione connect (): http://doc.trolltech.com/4.5/qobject.html#connect, http://doc.trolltech.com/4.5/qt.html# ConnectionType-enum

Per quanto ho capito, EVT_IDLE viene inviato quando la coda dei messaggi dell'applicazione è vuota. Non esiste un evento simile in Qt, ma se è necessario eseguire qualcosa in Qt in assenza di eventi in sospeso, è necessario utilizzare QTimer con 0 timeout.

In generale, il modo più Qt-ish è aggiornare il pulsante / barra degli strumenti come necessario in qualunque funzione richieda l'aggiornamento, oppure consolidare alcune delle funzionalità e chiamare direttamente quella funzione quando il programma ne ha bisogno (come un updateUi la funzione).

Dovresti essere consapevole che in Qt, la modifica di un attributo di un elemento dell'interfaccia utente non provoca un ridisegno immediato, ma mette in coda un ridisegno nel sistema degli eventi e più chiamate di ridisegno vengono compresse in una ove possibile.

Per quanto riguarda le molteplici modifiche relative allo stato, dai un'occhiata a questo post sul blog su un'aggiunta speranzosa in arrivo a Qt per gestire più facilmente gli stati. Sembra che questo si occuperebbe di molti dei tuoi reclami, perché nelle tue molteplici funzioni, potresti semplicemente spostare la variabile di stato e le altre parti dell'interfaccia utente dovrebbero aggiornarsi per corrispondere. Non è positivo che questo entrerà nella prossima versione di Qt (anche se scommetto su di esso, o qualcosa di simile), e non ho idea di quanto PyQt segua da vicino le versioni di Qt. In alternativa, è possibile utilizzare il concetto e creare la propria classe per tenere traccia dello stato, se necessario.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top