Come modificare la posizione del cursore di wxRichTextCtrl nel gestore eventi?
Domanda
Ho un RichTextCtrl nella mia applicazione, che ha un gestore per EVT_KEY_DOWN
. Il codice che viene eseguito è il seguente:
def move_caret(self):
pdb.set_trace()
self.rich.GetCaret().Move((0,0))
self.Refresh()
def onClick(self,event):
self.move_caret()
event.Skip()
rich è il mio RichTextCtrl.
Ecco cosa mi piacerebbe che facesse:
-
a ogni pressione del tasto, aggiungi la chiave al controllo (che è il comportamento predefinito)
-
sposta il cursore all'inizio del controllo, prima posizione
Ecco cosa fa effettivamente:
-
aggiunge la chiave al controllo
-
Ho ispezionato la posizione del punto di inserimento e il debugger segnala che si trova a 0,0 ma sul controllo, lampeggia nella posizione corrente (che è la posizione prima di premere un tasto + 1)
Vedi qualcosa di sbagliato qui? Ci deve essere qualcosa che sto facendo di sbagliato.
Soluzione
Apparentemente, ci sono due problemi con il tuo codice:
-
Ascolta
EVT_KEY_DOWN
, che probabilmente viene gestito prima diEVT_TEXT
, il cui gestore predefinito imposta la posizione del cursore. -
Modifichi l'oggetto
Caret
invece di usare il metodoSetInsertionPoint
, che sposta entrambi il cursore e fa apparire il carattere successivo in un determinato posto.
Quindi l'esempio funzionante (l'ho testato e funziona come vorresti) sarebbe:
# Somewhere in __init__:
self.rich.Bind(wx.EVT_TEXT, self.onClick)
def onClick(self, event):
self.rich.SetInsertionPoint(0) # No refresh necessary.
event.Skip()
MODIFICA : se vuoi che il testo venga aggiunto alla fine, ma il cursore rimanga all'inizio (vedi commenti), puoi trarre vantaggio dal fatto che EVT_KEY_DOWN
viene gestito prima di EVT_TEXT
(che a sua volta viene gestito dopo l'aggiunta del carattere). Quindi l'ordine degli eventi è:
- gestisci
EVT_KEY_DOWN
- aggiungi carattere nel punto di inserimento corrente
- gestisci
EVT_TEXT
L'aggiunta di un gestore di EVT_KEY_DOWN
che sposta il punto di inserimento alla fine appena prima di aggiungere effettivamente il personaggio fa il lavoro abbastanza bene. Quindi, oltre al codice menzionato in precedenza, scrivi:
# Somewhere in __init__:
self.rich.Bind(wx.EVT_KEY_DOWN, self.onKeyDown)
def onKeyDown(self, event):
self.rich.SetInsertionPointEnd()
event.Skip()
A proposito, event.Skip ()
non invoca immediatamente il gestore dell'evento successivo, semplicemente imposta un flag nell'oggetto evento
, in modo che il processore di eventi sappia se per interrompere la propagazione dell'evento dopo questo gestore.