Ruby で GTK+2 グラフィック
GTK+ といっても、GUIを作りたいのではないのです(そのうち GUI も作りたくなるかも)。ではなくて、簡単に線を引いたり円を描いたりしたい。Green Shoes でやればいい? Ruby/Tk でやればいい? いや、Linux だったらやはり GTK+ でしょう。GTK+2 でやりたい。
Linux ならば多分 GTK+2 は入っている筈。なければ「ソフトウェアの管理」(Linux Mint の場合)などからインストールする。
Ruby としては、とりあえず Gem 'gtk2' を入れる。ついでに 'gtk3' も入れておくとよい。
リファレンスは下のリンクを。しかしあまり日本語に翻訳されていないので、サイトを wget で全ダウンロードして、必要な部分だけ HTML を勝手に(翻訳して)書き換えてローカルで参照する。
Ruby-GNOME2 Project Website - Ruby-GNOME2 Project Website
試行錯誤しまくって、ようやく簡単なお絵かき成功。やっとですよ。
コードは以下。
require 'bundler/setup' require 'gtk2' w = Gtk::Window.new w.set_size_request(300, 300) w.set_app_paintable(true) w.realize drawable = w.window gc = Gdk::GC.new(drawable) colormap = Gdk::Colormap.system white = Gdk::Color.new(65535, 65535, 65535) red = Gdk::Color.new(65535, 0, 0) colormap.alloc_color(white, false, true) colormap.alloc_color(red , false, true) w.signal_connect("expose_event") do gc.set_foreground(white) drawable.draw_rectangle(gc, true, 0, 0, 300, 300) gc.set_foreground(red) drawable.draw_arc(gc, true, 0, 0, 300, 300, 0, 64 * 360) end w.show Gtk.main
注意しておくと、お絵かきで色を使うには、colormap に色を登録しておかないといけないようです。上だと colormap.alloc_color(white, false, true) などのところですね。それから、ウィンドウを paintable にしておかないとお絵かきできません。これは上だと w.set_app_paintable(true) のところですね。
下などが参考になります。
ウインドウへの直接描画(2) - Gdk::Drawable - Ruby-GNOME2 Project Website
カラーの扱い - Ruby-GNOME2 Project Website
上のブロックの部分だけ変えます。すると中心から円が拡大していき、画面の縁に達したところで停止します。
w.signal_connect("expose_event") do gc.set_foreground(white) drawable.draw_rectangle(gc, true, 0, 0, 300, 300) r = 1 id = Gtk.timeout_add(80) do gc.set_foreground(red) drawable.draw_arc(gc, true, 150 - r, 150 - r, r * 2, r * 2, 0, 64 * 360) Gtk.timeout_remove(id) if r > 150 r += 1 end end
キモは Gtk.timeout_add(80) のブロックで、80ミリ秒毎にブロックの中を実行します。
モジュール化
汎用部分をモジュール化してみました。
mygtk.rb
require 'bundler/setup' require 'gtk2' module MyGtk W = Gtk::Window.new class Tool def initialize @drawable = W.window @gc = Gdk::GC.new(@drawable) @colormap = Gdk::Colormap.system @color = Gdk::Color.new(0, 0, 0) end def color(r, g, b) @color = Gdk::Color.new(r, g, b) @colormap.alloc_color(@color, false, true) @color end def rectangle(x, y, width, height, color = nil) set_color(color) @drawable.draw_rectangle(@gc, true, x, y, width, height) end def arc(x, y, width, height, d1, d2, color = nil) set_color(color) @drawable.draw_arc(@gc, true, x, y, width, height, d1, d2) end def set_color(color) @color = color if color @gc.set_foreground(@color) end end def self.app(width: 300, height: 300, &bk) W.set_size_request(width, height) W.set_app_paintable(true) W.realize W.signal_connect("expose_event") {Tool.new.instance_eval(&bk)} W.show Gtk.main end end
上の画像はこれだけで描画できます。
require './mygtk' MyGtk.app width: 300, height: 300 do white = color(65535, 65535, 65535) red = color(65535, 0, 0) rectangle(0, 0, 300, 300, white) arc(0, 0, 300, 300, 0, 64 * 360, red) end
円が拡大していくバージョンは下。
MyGtk.app width:300, height: 300 do white = color(65535, 65535, 65535) red = color(65535, 0, 0) rectangle(0, 0, 300, 300, white) r = 1 id = Gtk.timeout_add(80) do arc(150 - r, 150 - r, r * 2, r * 2, 0, 64 * 360, red) Gtk.timeout_remove(id) if r >= 150 r += 1 end end
追記
これは結局ささやかな Gem にまで発展しました。以下を参照。
oekaki | RubyGems.org | your community gem host
GTK+でお絵かきしてみた(Ruby) - Camera Obscura