tkinter.Text で、IME の Ctrl-M 変換確定入力が捨てられる件
あんまりまじめに Python 3.0 を追いかけていなかったわたしですが、せっかく PC を新調したのでこれはいい機会と、 新しい環境では、Python 3.0 だけインストールして、 強制的に 2.x 環境からの移行を進めようと考えました。
そうして、お手製ツールの移植を始めたのですが、けっこういろいろ動かないもんですね。転けるところがお勉強ポイントなので、それはそれでいいのですが、いきなり 2.5 から 3.0 への移行はちょっと無謀だったかしら(^^; *1
そんなこんなでよく使う手製ツールはだいたい移行を終えたのですが、一つだけイヤンな問題が。以前、Python 2.4 -> 2.5 移行の時、直っていてうれしかった、tkinter.Textが Ctrl-M での ATOK の変換確定(全文確定)入力を捨ててしまう件が 3.0では 再発してしまってる様です。(あ、Windows環境です)
前は「直ったから、ま、いいか」で、全然調査してなかったのですが、そのときチラッと見た限りでは、たしかKeyイベントで拾うとそこでは変換確定入力が取れるんでしたよね、と思い出しました。とりあえず、どうにか避ける方法を検討するため、こんなコードを書いてKeyイベントをちょっと眺めてみます。
from tkinter import * from tkinter.scrolledtext import * class TestFrame( Frame ): def __init__(self, master=None): Frame.__init__(self, master) text = ScrolledText( self ) def onKey(evt): print('[%s](%s) keycode=%x keysym=%s type=%s' % (evt.char, '%02x' % ord(evt.char) if len(evt.char) != 0 else '', evt.keycode , evt.keysym, evt.type)) text.bind('<Key>',onKey) text.pack(side=TOP) self.pack(fill=BOTH) TestFrame().mainloop()
これで、普通に abc とか入力した場合
[a](61) keycode=41 keysym=a type=2 [b](62) keycode=42 keysym=b type=2 [c](63) keycode=43 keysym=c type=2
なふうにコンソールに出力が出ます。
これで早速、IME を使った入力を眺めてみます。すると、Enter とか 下矢印で確定した場合
[]() keycode=e5 keysym=?? type=2 # あ []() keycode=e5 keysym=?? type=2 # い []() keycode=e5 keysym=?? type=2 # う []() keycode=e5 keysym=?? type=2 # Enterとか↓ [あ](3042) keycode=0 keysym=?? type=2 [い](3044) keycode=0 keysym=?? type=2 [う](3046) keycode=0 keysym=?? type=2
と、Ctrl-M で確定した場合
[]() keycode=e5 keysym=?? type=2 # あ []() keycode=e5 keysym=?? type=2 # い []() keycode=e5 keysym=?? type=2 # う []() keycode=11 keysym=Control_L type=2 # Ctrl... []() keycode=11 keysym=Control_L type=2 # (キーリピート) []() keycode=11 keysym=Control_L type=2 []() keycode=11 keysym=Control_L type=2 []() keycode=11 keysym=Control_L type=2 []() keycode=11 keysym=Control_L type=2 []() keycode=11 keysym=Control_L type=2 []() keycode=11 keysym=Control_L type=2 []() keycode=e5 keysym=?? type=2 # ...M [あ](3042) keycode=0 keysym=?? type=2 [い](3044) keycode=0 keysym=?? type=2 [う](3046) keycode=0 keysym=?? type=2
では、本当に Ctrlキーが押しっぱなしなことくらいしか違いが無いみたいに見えます。みゅー、Ctrl修飾が掛かっていること自体がダメの原因かしら?でもなー。むーむ、なんだかよくわからにゃいな。
とりあえす、Ctrl修飾付きの Keyイベントをフックして、キーコードが 0 な入力を見つけたら、手前で text.insert してあげればうまく回避できるかな?なので、やってみます。
さっきのコードに、
class TestFrame( Frame ): def __init__(self, master=None): ・ ・ # IME Ctrl-M 確定入力パッチ def ime_ctrl_m(evt): if evt.keycode == 0: text.insert( INSERT, evt.char ) text.bind('<Control-Key>',ime_ctrl_m)
を追加。
いろんな入力操作を試してみましたが、いままでのところ暴走や二重入力もなく、こんな手抜き補修でも一応 大丈夫そうです。とりあえず、これで行きましょ。
ホントの所、なんでダメなのかはまたもや棚上げです。(ここらへんが ワナビクォリテイ)