イベントハンドラでwxRichTextCtrlのカーソル位置を変更するにはどうすればよいですか?
質問
アプリケーションにRichTextCtrlがあり、 EVT_KEY_DOWN
のハンドラーがあります。実行されるコードは次のとおりです。
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 は私のRichTextCtrlです。
これが私がやりたいことです:
-
キーを押すたびに、コントロールにキーを追加します(これはデフォルトの動作です)
-
コントロールの先頭、最初の位置にカーソルを移動します
実際に行うことは次のとおりです:
-
コントロールにキーを追加します
-
キャレットの位置を調べたところ、デバッガは0,0にあると報告しましたが、コントロール上では現在の位置(キーを押す前の位置+ 1)で点滅します
ここで何か問題がありますか?私が間違っていることをしているはずです。
解決
明らかに、コードには2つの問題があります:
-
EVT_KEY_DOWN
をリッスンします。これはおそらくEVT_TEXT
の前に処理されます。デフォルトハンドラーはカーソル位置を設定します。 -
SetInsertionPoint
メソッドを使用する代わりに、Caret
オブジェクトを変更します。これにより、キャレットが移動し、次の文字が所定の場所に表示されます。
したがって、実際の例(私はテストし、あなたが望むように動作します)は次のようになります:
# Somewhere in __init__:
self.rich.Bind(wx.EVT_TEXT, self.onClick)
def onClick(self, event):
self.rich.SetInsertionPoint(0) # No refresh necessary.
event.Skip()
編集:末尾にテキストを追加したいが、カーソルを先頭に残したい場合(コメントを参照)、 EVT_KEY_DOWN
は EVT_TEXT
の前に処理されます(これは文字の追加後に処理されます)。したがって、イベントの順序は次のとおりです。
- ハンドル
EVT_KEY_DOWN
- 現在の挿入ポイントに文字を追加
- ハンドル
EVT_TEXT
実際にキャラクターを追加する直前に挿入ポイントを最後に移動する EVT_KEY_DOWN
のハンドラーを追加すると、非常にうまく機能します。したがって、前述のコードに加えて、次のように記述します。
# Somewhere in __init__:
self.rich.Bind(wx.EVT_KEY_DOWN, self.onKeyDown)
def onKeyDown(self, event):
self.rich.SetInsertionPointEnd()
event.Skip()
ところで、 event.Skip()
はすぐに次のイベントハンドラを呼び出さず、 event
オブジェクトにフラグを設定するだけなので、イベントプロセッサはこのハンドラーの後のイベントの伝播を停止します。