From: Naoki Oshiro Date: 2015-03-08T17:11:40+09:00 Subject: [ruby-list:50100] Re: Ruby/Tkでのキャンバス上のアイテム作成 大城です。こんにちは。 2015年3月6日 19:44 Hidetoshi NAGAI : > キャンバスアイテムを色々と操作する場合には > オブジェクトとなっている方が扱いやすいのですが, > アイテム生成後の操作が不要であるような場合には > オブジェクトの生成は資源の無駄となりがちです. > create メソッドは,オブジェクトを生成することなくアイテムを作成するために > 用意したものとなります. 個別のアイテムクラスでも、キャンバスクラスのcreateでも同じアイテムオブジェクト(TkcItem)を生成するかと勘違いしていました。createではTkキャンバス上のidを返すのみでしたか(確認しますと、こちらはFixnumでした)。 > # create で作っておいて,後からオブジェクト化する手段もあります. > # ( create_itemobj_from_id メソッドとか ) あー、なるほど。これが可能なのであれば、例えば新規にTkcIdなどのクラスにTkキャンバス上のアイテムidを持たせておくようにして、このidオブジェクトへのコマンドメソッドへのアクセスがあった場合にのみmethod_missingから、TkcItemの各種アイテムオブジェクトを生成させるというようにすると、キャンバスクラスでのcreateでこのTkcIdを返しておけば、どちらの生成でもユーザ側からは見かけ上は同等に使えて、かつメモリ消費も最低限というような形にできるかもしれませんね。 TkcTagAccessモジュール (canvastag.rb) でTkcItemクラスに各アイテムへのコマンド割り当てがなされているのを今回知りました。また、tkclass.rbを使うと接頭のTkを外した形でのクラス名指定(TkCanvas⇒CanvasやTkcLine⇒Lineなど)もできるようになっていたのですね。こちらを使うと種々の基本的なクラス名(Frame, Label, Entry, Lineなど)がTk寄りになり過ぎる感もありますが。 >> また、PerlやPythonですと、キャンバスのアイテム作成用のメソッド名は create_line などがあるようです。 ... > こうしたメソッドを用意することも考えたのですが, > Tk 拡張でアイテムが追加される可能性を鑑みるとキリがないかなとも思って > 組み込むことは控えていました. ... > どうしても欲しければば,monky patch で追加してもらえばいいかなと. canvasは元がTclで使い慣れているので、私の場合は「.c create line XX YY」の語順に近いほうが馴染みがあるようです。gem化等々してみますかね(といっても、実質は先のメールで書いたclass_eval一行ですが…)。 >> Rubyのキャンバスクラスでも同じようなメソッド名にしてはどうかと、TkCanvas::createで使っているTkcItem::CItemTypeToClassのアイテム名/クラス名の情報を使って次のようにメソッドを定義してみました: >> >> class TkCanvas >> TkcItem::CItemTypeToClass.each do |k, v| >> class_eval("def create_#{k}(*args); #{v}.create(self, *args); end") >> end >> end >> >> 上記の定義を使うと以下で書けます。 >> >> c.create_line(10, 30, 100, 30, fill: "green") >> >> 他との類似も考えて、こちらあたりにしてもいいとも思うのですがいかがでしょうか? > > ご希望であれば,他にもこういう↓対応方法もありますね. > ----------------------------------------------------------- > class TkCanvas > def method_missing(id, *args) > name = id.id2name > if name =~ /^create_(.+)/ > __send__(:create, $1, *args) > else > super > end > end > end method_missingでの対応のご紹介ありがとうございました。こちらの場合は、create_XXXXのメソッドの使用時に毎回method_missingへの呼び出しが起こるのですよね?アイテム生成時のみですから、そこまでのコストではないのでしょうけど。 > 最初に書いたように,アイテムを操作する可能性があるか, > わずかであってもオブジェクトが占めるメモリを減らしたいか > というところが判断基準だと思っています. 現在見かけるRuby/Tkでのキャンバス使用の紹介では、(アイテム操作を必要としない描画のみの場合でも)ほとんどがアイテムクラスを使っている印象があります。両者の使い分けについては、あまり広まっていないのかもしれません。また、キャンバスで生成した場合でもアイテムidを使って操作できないわけではないので、こちらももう少し出ても良さそうな気もします。 逆に、もし使い分けの認知がされていない状況だとすれば、キャンバスクラスでのcreate時にもTkcItemを生成させてそのアイテムを操作できるよう統一したほうがわかりやすいのかもしれませんね。そう言えば、TclからTkを使っていた際に、いちいちキャンバスを経由してmoveやらitemconfigureなどでアイテムを間接的に操作するのを面倒に思ったこともありました。生成時にはキャンバスに指令して、生成後のアイテムはそれ自身に指令という折衷案もアリかもしれません。 ありがとうございました。 --- ============================================= OSHIRO Naoki: oshiro@mibai.tec.u-ryukyu.ac.jp http://mibai.tec.u-ryukyu.ac.jp/~oshiro/