Ruby/GTK+ でちょっと考えた

以前に RubyGUI で、ここ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

 
こんなのでどうでしょうか。
20180803180629

わんわん
にゃー
わんわん
わんわん
にゃー

「イヌ」ボタンの方はこんなメッセージダイアログが出ます。
20180803235524
 
Gtk2 を使っているのは、既に枯れた技術だから。いまなら Gtk3 の方がよいのかも知れません。なお、以上は Linux でやっていますが、Gtk2 なら Windows でもふつうに動きます。Gtk3 はどうか知らない。

Ruby/GTK+ は面倒という人もいるようだが、上を見てもらえばそれほど面倒でないとわかると思う。


Ruby/GTK+ の日本語サイトもまだ更新されていて頼もしいです。
Ruby-GNOME2 Project Website - Ruby-GNOME2 Project Website


追記(8/4)
ブロック内でメソッドを定義するバージョンも考えてみました。
Ruby/GTK+ でちょっと考えた · GitHub