Comment changer la position du curseur de wxRichTextCtrl dans le gestionnaire d'événements?
Question
J'ai une application RichTextCtrl dans mon application, dotée d'un gestionnaire pour EVT_KEY_DOWN
. Le code exécuté est le suivant:
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 est mon RichTextCtrl.
Voici ce que je voudrais qu'il fasse:
-
à chaque pression de touche, ajoutez la clé au contrôle (comportement par défaut)
-
déplace le curseur au début du contrôle, première position
Voici ce qu'il fait réellement:
-
ajoute la clé au contrôle
-
J'ai inspecté la position du curseur, et le débogueur a signalé qu'il se trouvait à 0,0 mais sur le contrôle, il clignote à la position actuelle (position avant que j'aie appuyé sur la touche + 1)
Voyez-vous quelque chose qui ne va pas ici? Il doit y avoir quelque chose que je fais mal.
La solution
Apparemment, votre code pose deux problèmes:
-
Vous écoutez
EVT_KEY_DOWN
, qui est probablement traité avantEVT_TEXT
, dont le gestionnaire par défaut définit la position du curseur. -
Vous modifiez l'objet
Caret
au lieu d'utiliser la méthodeSetInsertionPoint
, qui déplace le curseur et fait apparaître le caractère suivant à un endroit donné.
Ainsi, l'exemple de travail (je l'ai testé et il fonctionne comme vous le souhaitez) serait:
# Somewhere in __init__:
self.rich.Bind(wx.EVT_TEXT, self.onClick)
def onClick(self, event):
self.rich.SetInsertionPoint(0) # No refresh necessary.
event.Skip()
MODIFIER : si vous souhaitez que le texte soit ajouté à la fin, mais que le curseur reste au début (voir les commentaires), vous pouvez tirer parti du fait que EVT_KEY_DOWN
est traité avant EVT_TEXT
(qui à son tour est traité après l’ajout de caractères). Donc, l'ordre des événements est:
- handle
EVT_KEY_DOWN
- ajouter un caractère au point d'insertion actuel
- gérer
EVT_TEXT
L'ajout d'un gestionnaire de EVT_KEY_DOWN
qui déplace le point d'insertion à la fin juste avant d'ajouter le caractère, fait le travail assez bien. Ainsi, en plus du code mentionné précédemment, écrivez:
# Somewhere in __init__:
self.rich.Bind(wx.EVT_KEY_DOWN, self.onKeyDown)
def onKeyDown(self, event):
self.rich.SetInsertionPointEnd()
event.Skip()
Au fait, event.Skip ()
n'invoque pas immédiatement le gestionnaire d'événement suivant, mais définit un indicateur dans l'objet event
, afin que le processeur d'événements sache si pour arrêter la propagation de l'événement après ce gestionnaire.