Ruby/Gtk2 でカスタムウィジェットを作る
長いあいだ Ruby/Gtk2 でカスタムウィジェットの作りかたがよくわからなかったけど、今日 rbbr を読んでいてやりかたがわかった。クラス定義の中で GLib::Object.type_register を呼び出して GObject システムに型を登録してから、GLib::MetaInterface.signal_new でシグナルを登録するらしい。
ためしに、2つあるトグルボタンを両方とも押し込まないと状態が ON にならない DualButton ウィジェットクラスを作ってみた。
# -*- coding: utf-8 -*- require 'gtk2' include Gtk class DualButton < HButtonBox type_register signal_new("toggled", GLib::Signal::ACTION, nil, GLib::Type["void"]) def initialize super self.spacing = 10 @active = false @first_button = ToggleButton.new(" 左 ") @second_button = ToggleButton.new(" 右 ") pack_start(@first_button) pack_start(@second_button) [@first_button, @second_button].each do |button| button.signal_connect('toggled') do recalc_state end end end def recalc_state state = @first_button.active? && @second_button.active? if state != @active @active = state signal_emit('toggled') end end def active? @active end end
見ため的にはボタンを左右に 2 つならべただけのウィジェットなので HButtonBox を継承する。両方のトグルボタンの状態を監視して、条件が揃ったら自身が toggled シグナルを送出する。on/off の状態は active? メソッドで公開している。
def main window = Window.new window.border_width = 20 dual_button = DualButton.new dual_button.signal_connect('toggled') do puts "dual button #{dual_button.active? ? 'on' : 'off'}" end window.add dual_button window.signal_connect('destroy') { Gtk.main_quit } window.show_all Gtk.main 0 end exit main
クライアント部分は、DualButton の状態が変化したら端末に on/off を出力するというものだ。
左を押し下げて、右も下げると on になる。
ここで右を上げると off になって、さらに左を上げても off のままなのでシグナルは送出されない。
これで UI クラスの間での通信は GTK っぽくシグナルを使うことができるようになった。