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

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

# はじめての Ruby/GTK

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

```ruby:simple.rb
require 'gtk3'
window = Gtk::Window.new
window.show
Gtk.main
```
![screenshot.png](https://qiita-image-store.s3.amazonaws.com/0/144608/c40b7524-f2d1-e682-f318-28a52192583b.png)
うまく表示されましたでしょうか？　このままだと画面を閉じてもアプリは終了しないので、ターミナルで Ctrl + C を打って終了してください。画面を閉じた時にアプリを終了するときは、次のようにします。

```ruby: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した時に、アプリを終了するという意味になります。

![screenshot2.png](https://qiita-image-store.s3.amazonaws.com/0/144608/a97f1360-18ed-4e92-89dc-a2798e53e53c.png)
↑ Xボタンをクリックすると終了する。

# Glade を準備する
　Glade とは、GTK 向けの GUI ビルダーです。このツールを使っている人は多分少ないと思うのでインストールしなければならない方が多いと思います。スクリーンショットはこんな感じです。
![screenshot3.png](https://qiita-image-store.s3.amazonaws.com/0/144608/87e374dd-d8b6-1645-273c-2b6104198fb2.png)
Gladeは、 Macでは`homebrew`で、Ubuntuでは`apt`でインストールできます。Windowsでは、公式ホームページで配布されている binaryが古いため MSYS2でpacmanパッケージマネージャーを使ってインストールする方法がよいようです。RubyInstallerでDevKit付属のRubyをインストールした方は、すでにMSYS2が入っているかもしれないので、Rubyをインストールしたフォルダ内を探してみてください。

# Gladeを使ってボタンだけの簡単なアプリをつくる
1. Gladeの操作
2. コードを書く

に分けて説明します。

## 1.Glade の操作
1. 新しいプロジェクトを作成します。
![screenshot4.png](https://qiita-image-store.s3.amazonaws.com/0/144608/213f8aab-6b52-2010-a688-7f231dafe6b1.png)
2. トップレベルから GtkWindow を作ります。
![screenshot5.png](https://qiita-image-store.s3.amazonaws.com/0/144608/6ffa0afd-fa20-91b9-9e09-86aead97e8c7.png)
3. コンテナからGtkWindowに GtkFixed を追加します
![screenshot9.png](https://qiita-image-store.s3.amazonaws.com/0/144608/be624c0e-9b6d-7ba6-124c-54cda430c7f3.png)
4. Controlから ボタン (GtkButton) を配置します。
![screenshot11.png](https://qiita-image-store.s3.amazonaws.com/0/144608/fa083b64-6447-1057-8ba7-c16cc44f0246.png)
ボタンを中央に配置しました。
![screenshot12.png](https://qiita-image-store.s3.amazonaws.com/0/144608/aa6d4397-d2cd-9af5-2efd-30c98b9f0559.png)
5. 見た目を整えるために、GtkWindowのサイズを指定しましょう。ここでは幅440 高さ250とします。
![screenshot13.png](https://qiita-image-store.s3.amazonaws.com/0/144608/8827d8b1-b66f-4e08-fcbe-5f9bc06ffd57.png)
6. ウィンドウに`win`というIDをつけます。これは、あとでRuby側からウィンドウを表示するためです。
![screenshot16.png](https://qiita-image-store.s3.amazonaws.com/0/144608/b9be29e1-5b05-657e-8026-5f25e5857ea9.png)
7. ボタンに`button`というIDをつけます。これは、あとからRuby側でボタンのオブジェクトを扱えるようにするためです。（今回は、やらなくてもアプリの動作には影響しません。）
![screenshot17.png](https://qiita-image-store.s3.amazonaws.com/0/144608/65257d57-cf42-2173-1cb5-b693e3b3d2b4.png)
8. ウィンドウを閉じるイベントが発生した時に何かの動作をさせるためにGtkWindowにdestroyシグナルのハンドラを設定します。ここでは on_win_destroy とします。あとでRubyの同名のメソッドに接続して、ウィンドウが閉じた時にアプリを終了するようにします。
![screenshot14.png](https://qiita-image-store.s3.amazonaws.com/0/144608/e542da76-ac68-33cb-2d6b-7a2232932ecb.png)
9. ボタンをクリックした時に何かの動作させるためにGtkButtonにclickedシグナルのハンドラを設定します。ここでは on_button_clicked とします。あとでRubyの同名のメソッドに接続します。
![screenshot15.png](https://qiita-image-store.s3.amazonaws.com/0/144608/bcd66dd6-2e9a-9868-4569-d7acaee4ba4e.png)
10. 保存します。ここでは`myapp.glade`という名前をつけて保存しました。（このファイルの中身はXMLなので、テキストエディタでも閲覧・編集することが可能です。）
（ここまで慣れれば5分ぐらいだと思います。）

## 2.コードを書く
基本形式は以下の通りです。

```ruby
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` とすることで生成されたオブジェクト一覧を見ることができます。

```terminal
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も終了するためのメソッドを用意します。

```ruby
def on_win_destroy
  Gtk.main_quit
end
```

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

```ruby
@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`

# アプリを起動する
ボタンを押します。
![screenshot18.png](https://qiita-image-store.s3.amazonaws.com/0/144608/0bdd9df3-68b4-90ee-8669-846e3f8fe851.png)

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

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

```
やあ、君はボタンを1760回押したね！
やあ、君はボタンを1761回押したね！
やあ、君はボタンを1762回押したね！
やあ、君はボタンを1763回押したね！
やあ、君はボタンを1764回押したね！
```
ポチポチポチポチ　ポチポチポチポチ　ポチポチポチポチ　ポチポチポチポチ　ポチポチポチポチ…

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

![inu_shippo_oikakeru.png](https://qiita-image-store.s3.amazonaws.com/0/144608/7d07d472-7816-ab7b-83df-7fecec8c6014.png) ﾎﾟﾁ

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

![screenshot19.png](https://qiita-image-store.s3.amazonaws.com/0/144608/f6b06577-fa15-546f-0734-a7508802f563.png)

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

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

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