Thu May 20 23:58:38 JST 1999
UNDER CONSTRUCTION :)
技術メモその他あれこれ


僕のところに溜っているだけ、もしくはあまり知られてない、もしくはみんなが知ってるけどあんまし文書として出てない Tcl/Tk 8.0jp (主に UNIX 版)がらみのあれこれをまとめてみました。



configure, make など、いわゆる Compile 一般の FAQ


  • 「Solaris 2.x で patch が当たらないんだけど、なんで?」
    Solaris 2.x 附属の patch コマンドを使っているからでしょう。最新の patch コマンドを使えば OK です。


  • 「tk の configure の --enable-xlibHack をつけるとコンパイルできないんですけど」
    --enable-xlibHack は、XFree86 3.x でないと動きません。そういうもんです。 その気になれば、X11R6.x でも、動かせます。頑張って下さい B) ちなみに、 こいつをつけると、XIM プロトコルで {PreeditSpot StatusArea} などの over-the-spot 変換モードを使っている時の IM サーバ用のフォントのロード (XCreateFontset() の処理)が「劇的」に速くなります。っつーか、明らかに Xlib の bug で XCreateFontset() が遅くなっているのを直しているのがミソ なだけです。もっと言うと、XFree86 のソースツリーの xc/lib/X11 に、 unix/CacheLib/omGeneric.c を cp して Xlib を make し直すと、 XCreateFontset() が速くなります :)



    日本語入力関係 FAQ


  • 「漢字入力ができない!」
    環境変数 XMODIFIERS を、"@im=none" としてると、Tk は XMODIFIRES が設定 されているという理由だけで XIM プロトコルを使おうとします。が、"使う IM は無いよ" と Xlib に教えているので IM サーバとお話しません。しかも、 XIM プロトコルの使用と kinput2 プロトコルの使用は exclusive なので、こ の設定では 「んじゃ代わりに kinput2 プロトコルを使おう」などと Tk は思 いません。だから日本語入力は完全に不可能になります。
    というわけで、 将来的には、XMODIFIERS の有無で漢字入力プロトコルを決めるのは止めよう と思っています。が、現状、これで困った、という例を一例しか知らんので、 いつになるかわかりません B)。
    現状、これを回避するのに一番簡単なの は、X リソースデータベースに tkKanjiConversionProtocol リソースを設定 するか、もしくは環境変数 TK_KCPROTO を設定することです。
    追加: tk8.0.5jp1.7 からは、XMODIFIERS が "@im=none" の場合には kinput プロト コルを使うように変更されています。


  • 「Solaris 2.x の htt とではうまく使えない」
    僕もです。kinput2 とでは当然うまく動くのは確認してるし、xwnmo, VJE で もうまく動いているとの報告はたくさんあるので、僕としては htt が悪いと 思ってます。なんとかして>Sun.


  • 「XIM 使用時に入力した漢字が文字化けするんですけど」
    多分 locale 名の問題です。IM サーバの動いているマシンと Tk が動いてい るマシンが違っていて、両者で同じ Japanese という locale 名を使っている とします。この状態で、IM サーバの動いているマシンでの Japanese は SJIS を指し、Tk が動いているマシンでの Japanese は EUC を指している、という のは大変ありがちです(例えば、IM サーバが HP-UX, Tk が Solaris の場合な ど)。
    解決方法は、ja_JP.eucJP など、ambiguous でない locale 名を使 用することです。


  • 「あるウィジェットで入力を行なおうとして、キーボードフォーカスを入れる(マウスの 1 ボタンをクリックする)と、しばらく動きが止まるんですけど」
    前述の、--enable-xlibHack オプションを付けてなくて、特に遅いマシンで X サーバを動かしている場合にこうなります。理由は、これまた前述のように、 XCreateFontset() が Xlib の bug のため、不当に遅いからです。
    --enable-xlibHack が使用可能である環境なら、これを指定して下さい。 そうでない環境の人は、素直にあきらめるか、Open group (現在の X の元締 め)に文句を言うように B)


  • 「canvas ウィジェットでの入力はどうすればいいの?」
    canvas の text アイテムの生成時には全くイベントがバインドされてないの で、単に作っただけでは、日本語に限らず何にも入力できないことを「まず」 覚えておいて下さい。
    で、どうするか、というと、手っ取り早いのは $tk_library/demos.jp/ctext.tcl を読むことです B)。このデモでは、Kinput プロトコル、XIM プロトコルそれぞれで日本語入力も可能にしてあります。


  • 「entry ウィジェットで on-the-spot 変換モードを使用したいんだけど」
    現状、デフォルトでは出来ません ^^; 誰か entry 用の on-the-spot コール バックプロシジャ書いて下さい _o_
    ちょっと言い訳: なんで出来んかと言 うと、entry には text のように Tag がないからなんですぅ。



    その他 Tk にまつわる Tips :)


  • 「"destroy ." を呼んで終了すると、異常に遅いんですけど、なんとかならんか?」
    多分、そんなあなたは "." に <Destroy> イベントを bind しているのでしょ う :) でもって、一度生成した "." の子供は終了するまで destroy しないよ うなスクリプトを書いているのでしょう :) (もし、ここで "." の子供を破壊 するようなコードであれば、以下に述べることにはとっくに気がついているは ずだから B)
    すべてのウィジェットインスタンスは、bindtag として "." のバインドを引 き継いでいます。したがって、"destroy ." として "." を破壊すると、"." の子供が破壊される瞬間に、"." の Destroy ハンドラが全ての子供に対して 次々と呼ばれることになります。これは遅いだけでなく、思わぬエラーを引き 起こすことがあります(例えば、一度 unset した変数を何回も unset したり、 テンポラリファイルを何回も消そうとしたり...。逆に、"." の子供を destroy した瞬間に、"." の Destroy ハンドラが呼ばれてしまって悲しい思 いをするとか)。
    こいつを避けるには、ちょっとした工夫をすれば OK で す。何をするかというと、"destroy ." を行なう前に、「"." を除くすべての ウィジェットインスタンスの bindtag から、"." を削除する」を行なうわけ です。方法は各自考えるように B)


  • フォントの pixel サイズ指定と point サイズ指定
    Tk のフォントサイズの指定は、point サイズが基本です。とはいえ、X の漢 字フォントを任意の point サイズで使用しようとすると bitmap resizing さ れてしまいます。これを防ぎたいなら、サイズを指定する時に負の数を与えま す。{Courier 14} は 14 ポイントの Courier を指し、{Courier -14} は 14 ピクセルの Courier を指します。混同しないように。


  • "update" と "update idletasks" の違い
    X の描画の完了(例えば pack などによってジオメトリの再計算が発生、その 描画が完了する、など)を待ってから処理を続行させなければならない場合、 "update idletasks" は役にたちません。"update" を使います。マニュアルに、 「何が "update idletasks" を使うべきで、何が "update" を使うべきか」が 明示的に書いてないのが悲しいのですが、"update idletasks" では意図した 結果が得られない場合、迷わず "update" に変えることで問題が解決すること は良くあります :)
    Xlib によるプログラミング経験がある人なら、「Tk での "update" は確実に XSync() を伴うが、"update idletasks" はそうでない」 と覚えておけば問題ないはずです :)


  • "tkwait visibility" の落し穴
    "tkwait visibility" によって、ある toplevel が表示されるのを待つのは、 常に正しく動くとは限りません。なぜなら、toplevel を生成した瞬間にそれ が Map されてしまう可能性があるからです。Map されたあとに visivility が変わるのはそれが他のウィンドウで隠された/iconfy された時になるので、 最悪無限に待ち続けます。特に、toplevel を生成し、その後間を空けて "tkwait visibility" が発行されるような場合に問題がでやすくなります。
    確実に待つなら、toplevel を生成した直後に、まず "wm withdraw" で Unmap してやって、用意が出来たら
    
    after 100 "wm deiconify .top; update"
    tkwait visibility .top
    
    くらいが良いでしょう。after 100 ... が嫌なら、
    
    global topIsMapped
    set topIsMapped 0
    bind .top <Map> {global topIsMapped; set topIsMapped 1}
    wm deiconify .top
    while {1} {
    	update
    	if {$topIsMapped == 1} {
    		break
    	}
    }
    unset topIsMapped
    bind .top <Map> {}
    
    などと大げさに書くこともできます :) またまた、この spin wait が嫌なら、 TclX の select コマンド使ってX の socket discriptor を passive wait す るとか、まぁいろいろ手はあるはずです。各自考えるように B)