以前に Ruby の GUI で、ここの Ruby/Tk でやろうとしていることを Green Shoesでやろうとしてみた。
obelisk.hatenablog.com
でもそれは元記事の意図とはちがっていて、「ボタンを押した時に、多重入れ子構造で内側に配置したウィジェットから外側に定義したメソッドを呼びたい」のであるとコメントを頂いた。それができると、いろいろ捗るということなわけですね。
暇なので、Ruby/GTK+ でもう一度考えてみた。基本的な考え方としては、ボタンを押したときに呼ばれるブロックを、外へ持ち出せばよい。そのとき、ブロックを呼び出したいインスタンス・メソッドに紐づける。
gtk_sample2b.rb
require 'gtk2' class GUI < Gtk::Window Meth = [:wanwan, :nya] def initialize super("GUI") set_width_request(200) box = Gtk::VBox.new add(box) @button1 = Gtk::Button.new("イヌ") @button2 = Gtk::Button.new("ネコ") label1 = Gtk::Label.new("吾輩はイヌである") label2 = Gtk::Label.new("吾輩はネコである") [@button1, label1, @button2, label2].each do |widget| box.pack_start(widget, true, true, 5) end @meth = {} signal_connect("destroy") {Gtk.main_quit} end Meth.each do |name| define_method(name) {|&bk| @meth[name] = bk} end def mainloop [@button1, @button2].zip(Meth).each do |bt| bt[0].signal_connect("clicked", &@meth[bt[1]]) end show_all Gtk.main end end g = GUI.new g.wanwan do puts "わんわん" md = Gtk::MessageDialog.new(g, Gtk::Dialog::MODAL, Gtk::MessageDialog::INFO, Gtk::MessageDialog::BUTTONS_OK, "わんわん") md.signal_connect("response") {md.destroy} md.run end g.nya {puts "にゃー"} g.mainloop
わんわん にゃー わんわん わんわん にゃー
「イヌ」ボタンの方はこんなメッセージダイアログが出ます。
Gtk2 を使っているのは、既に枯れた技術だから。いまなら Gtk3 の方がよいのかも知れません。なお、以上は Linux でやっていますが、Gtk2 なら Windows でもふつうに動きます。Gtk3 はどうか知らない。
Ruby/GTK+ は面倒という人もいるようだが、上を見てもらえばそれほど面倒でないとわかると思う。
Ruby/GTK+ の日本語サイトもまだ更新されていて頼もしいです。
Ruby-GNOME2 Project Website - Ruby-GNOME2 Project Website
※追記(8/4)
ブロック内でメソッドを定義するバージョンも考えてみました。
Ruby/GTK+ でちょっと考えた · GitHub