【Ruby】10分でGladeを使って作るRuby/GTK3 GUIアプリ


Ruby/GTK はRubyでGUI を組むことができるツールキットです。インターネット上の情報が少ないですが、Gladeと組み合わせると便利なのでまとめていこうと思います。
(タイトルは元々5分だったのですが、少し無理があるかな…と思ったので10分にしました。)
(内容や用語がおかしいところに気がついたらぜひご指摘ください。)

はじめての Ruby/GTK

まずgtk3のインストール。
gem install gtk3
Windowsの場合は接続できませんでしたというエラーが出たりしますが、そこでキャンセルせずに気長に待つとインストールされたりします。最初にウィンドウを表示してみます。

simple.rb
require 'gtk3'
window = Gtk::Window.new
window.show
Gtk.main


うまく表示されましたでしょうか? このままだと画面を閉じてもアプリは終了しないので、ターミナルで Ctrl + C を打って終了してください。画面を閉じた時にアプリを終了するときは、次のようにします。

simple.rb
require 'gtk3'
window = Gtk::Window.new
window.signal_connect(:destroy) { Gtk.main_quit } # 追加
window.show
Gtk.main

window.signal_connect(:destroy) { Gtk.main_quit }
は、windowをdestroyした時に、アプリを終了するという意味になります。


↑ Xボタンをクリックすると終了する。

Glade を準備する

 Glade とは、GTK 向けの GUI ビルダーです。このツールを使っている人は多分少ないと思うのでインストールしなければならない方が多いと思います。スクリーンショットはこんな感じです。

Gladeは、 Macではhomebrewで、Ubuntuではaptでインストールできます。Windowsでは、公式ホームページで配布されている binaryが古いため MSYS2でpacmanパッケージマネージャーを使ってインストールする方法がよいようです。RubyInstallerでDevKit付属のRubyをインストールした方は、すでにMSYS2が入っているかもしれないので、Rubyをインストールしたフォルダ内を探してみてください。

Gladeを使ってボタンだけの簡単なアプリをつくる

  1. Gladeの操作
  2. コードを書く

に分けて説明します。

1.Glade の操作

  1. 新しいプロジェクトを作成します。
  2. トップレベルから GtkWindow を作ります。
  3. コンテナからGtkWindowに GtkFixed を追加します
  4. Controlから ボタン (GtkButton) を配置します。 ボタンを中央に配置しました。
  5. 見た目を整えるために、GtkWindowのサイズを指定しましょう。ここでは幅440 高さ250とします。
  6. ウィンドウにwinというIDをつけます。これは、あとでRuby側からウィンドウを表示するためです。
  7. ボタンにbuttonというIDをつけます。これは、あとからRuby側でボタンのオブジェクトを扱えるようにするためです。(今回は、やらなくてもアプリの動作には影響しません。)
  8. ウィンドウを閉じるイベントが発生した時に何かの動作をさせるためにGtkWindowにdestroyシグナルのハンドラを設定します。ここでは on_win_destroy とします。あとでRubyの同名のメソッドに接続して、ウィンドウが閉じた時にアプリを終了するようにします。
  9. ボタンをクリックした時に何かの動作させるためにGtkButtonにclickedシグナルのハンドラを設定します。ここでは on_button_clicked とします。あとでRubyの同名のメソッドに接続します。
  10. 保存します。ここではmyapp.gladeという名前をつけて保存しました。(このファイルの中身はXMLなので、テキストエディタでも閲覧・編集することが可能です。) (ここまで慣れれば5分ぐらいだと思います。)

2.コードを書く

基本形式は以下の通りです。

require 'gtk3'

builder = Gtk::Builder.new(file: 'myapp.glade')

win = builder.get_object('win')
button = builder.get_object('button')

# [✕] が押された時にアプリを終了する
def on_win_destroy
  Gtk.main_quit
end

# ボタンがクリックされた時にターミナルに出力する
@counter = 0
def on_button_clicked
  puts "やあ、君はボタンを#{@counter}回押したね!"
  @counter += 1
end

builder.connect_signals { |handler| method(handler) } # handler は String

win.show_all
Gtk.main

一行ずつ詳しく見てみます。

まずXMLからウィジェットを自動生成するためにビルダーを作成してファイルを読ませます。
`builder = Gtk::Builder.new(file: 'myapp.glade')

p builder.objects とすることで生成されたオブジェクト一覧を見ることができます。

irb> ap builder.objects
[
    [0] #<Gtk::Window:0x5644050f3b70 ptr=0x564405f08260>,
    [1] #<Gtk::Button:0x5644050f3b20 ptr=0x564405ec8180>,
    [2] #<Gtk::Fixed:0x5644050f3af8 ptr=0x56440504f270>
]

ビルダーからウィンドウを取り出します。
win = builder.get_object('win')

ビルダーからボタンを取り出します。
button = builder.get_object('button')
今回この行は不要です。しかし、Gtk::Labelなど他のオブジェクトを取り出す際にも応用できるので、テンプレート的な意味で書いてみました。

ウィンドウを閉じた時にGTKも終了するためのメソッドを用意します。

def on_win_destroy
  Gtk.main_quit
end

ボタンを押した時に発動するためのメソッドを用意します。

@counter = 0
def on_button_clicked
  puts "やあ、君はボタンを#{@counter}回押したね!"
  @counter += 1
end

シグナルをRubyのメソッドに接続します。これを書くのを忘れがちなので注意してください。
builder.connect_signals { |handler| method(handler) } # handler は String

ウィンドウを表示します。
win.show_all

メインループを起動します。
Gtk.main

アプリを起動する

ボタンを押します。

やあ、君はボタンを0回押したね!
やあ、君はボタンを1回押したね!
やあ、君はボタンを2回押したね!
やあ、君はボタンを3回押したね!
やあ、君はボタンを4回押したね!

ポチポチポチポチ ポチポチポチポチ ポチポチポチポチ ポチポチポチポチ ポチポチポチポチ…

やあ、君はボタンを1760回押したね!
やあ、君はボタンを1761回押したね!
やあ、君はボタンを1762回押したね!
やあ、君はボタンを1763回押したね!
やあ、君はボタンを1764回押したね!

ポチポチポチポチ ポチポチポチポチ ポチポチポチポチ ポチポチポチポチ ポチポチポチポチ…

ふぅ、今日はだいぶボタンをクリックしました。指が疲れてきたので、この辺で失礼します。

ポチ

Tips

  • Ruby/Gtk はあまりドキュメントがないので、ウィジェットの使い方を手っ取り早く調べたいときはGladeの画面から目的のウィジェットを右クリックして、「マニュアルの参照」を見るのが早いです。他の環境では確認していませんが、Ubuntuでは英語のDevHelpが起動します。英語難しい(涙)

  • Glade は割と動作が不安定です。ウィジェットは直接ウィンドウをクリックせずに、左サイドのリストから選択するとクラッシュしにくいです。

参考資料

この記事を書くにあたって参考にしたサイト

Ruby/GTK3を今時のGlade, XML, Builder, CSSで書く1- 基本,ウィンドウ
http://blog.livedoor.jp/noanoa07/archives/2143075.html