Ruby-GNOME2 を用いたフォームのデザイン
フォームのデザインについて、次のことを例を使って説明する.
- 複数のフォーム部品から構成されるフォーム
ラベル,セパレータ,ラジオボタン,ブーレアン・チェックボタン,セレクトメニュー,1行テキスト,テキストエリア, カレンダー,submit ボタン
- フォームデータとオブジェクトのマッピング
ラベル,セパレータ,ラジオボタン,ブーレアン・チェックボタン,チェックボタン,セレクトメニュー,1行テキスト,テキストエリア,カレンダー,テーブル
Ruby-GNOME2 なので,漢字コードとして utf-8 を使うことにします.
* 画面遷移,フォーム部品の配置等に関する設計については,この Web ページの範囲外とします.
* Ruby-GNOME2 のインストール手順は, 「Windows で Ruby-GNOME2 のビルドとインストール」の Web ページ, 「Linux で Ruby-GNOME2 のビルドとインストール」のページで説明している.
説明に使うフォームの例

パッキングボックス (packing box)
- 水平パッキングボックスの生成: Gtk::HBox.new
Gtk::HBox.new(homogeneous, spacing)
- homogeneous: パッキングボックス内のオブジェクトを同じサイズにするか
- spacing: オブジェクト間の領域の大きさ
- 垂直パッキングボックスの生成: Gtk::VBox.new
Gtk::VBox.new(homogeneous, spacing)
- アラインメントの設定: Gtk::Box#set_alignment
set_alignment(x,y)
pack_start, pack_end の前に呼び出す.
- 上または左からの配置: Gtk::Box#pack_start
Gtk::Box#pack_start(child, expand, fill, padding)
- child:
- expand:
true ならば,パッキングボックスは領域全体に広がり,パッキングボックス内の Widget は余分な領域を残さないように配置される.false ならば Widget の右揃え,左揃えができるようになる.
- fill:
expand が true のときにのみ有効.true ならばオブジェクトは割り当て領域にあわせて広がる.false ならばオブジェクトは元の大きさのまま.
- padding: オブジェクトの両端におかれるすき間
- 下または右からの配置: Gtk::Box#pack_end
Gtk::Box#pack_end(child, expand, fill, padding)
* パッキングの例, expand = false, fill = false
#! ruby -Ku # -*- coding: utf-8 require 'gtk2' w = Gtk::Window.new w.set_title "Form" w.signal_connect('delete_event') do Gtk.main_quit false end box = Gtk::VBox.new(false, 10) w.add(box) box2 = Gtk::VBox.new(false, 10) box.add(box2) box2.pack_start( Gtk::Label.new("食べ物"), false, false, 0 ) box2.pack_start( Gtk::Label.new("飲み物"), false, false, 0 ) box2.pack_start( Gtk::Label.new("デザート"), false, false, 0 ) box.pack_start(box2) box3 = Gtk::HBox.new(false, 10) box.add(box3) box3.pack_start( Gtk::Label.new("福岡"), false, false, 0 ) box3.pack_start( Gtk::Label.new("大分"), false, false, 0 ) box.pack_start(box3) w.show_all Gtk.main

(a) 実行結果

(b) (a) のように表示されたあと、ウインドウのサイズを大きくした結果.上詰め,左詰めが維持される.
* パッキングの例, expand = true, fill = false
#! ruby -Ku # -*- coding: utf-8 require 'gtk2' w = Gtk::Window.new w.set_title "Form" w.signal_connect('delete_event') do Gtk.main_quit false end box = Gtk::VBox.new(false, 10) w.add(box) box2 = Gtk::VBox.new(false, 10) box.add(box2) box2.pack_start( Gtk::Label.new("食べ物"), true, false, 0 ) box2.pack_start( Gtk::Label.new("飲み物"), true, false, 0 ) box2.pack_start( Gtk::Label.new("デザート"), true, false, 0 ) box.pack_start(box2) box3 = Gtk::HBox.new(false, 10) box.add(box3) box3.pack_start( Gtk::Label.new("福岡"), true, false, 0 ) box3.pack_start( Gtk::Label.new("大分"), true, false, 0 ) box.pack_start(box3) w.show_all Gtk.main
* パッキングの例, expand = true, fill = true
#! ruby -Ku # -*- coding: utf-8 require 'gtk2' w = Gtk::Window.new w.set_title "Form" w.signal_connect('delete_event') do Gtk.main_quit false end box = Gtk::VBox.new(false, 10) w.add(box) box2 = Gtk::VBox.new(false, 10) box.add(box2) box2.pack_start( Gtk::Label.new("食べ物"), true, true, 0 ) box2.pack_start( Gtk::Label.new("飲み物"), true, true, 0 ) box2.pack_start( Gtk::Label.new("デザート"), true, true, 0 ) box.pack_start(box2) box3 = Gtk::HBox.new(false, 10) box.add(box3) box3.pack_start( Gtk::Label.new("福岡"), true, true, 0 ) box3.pack_start( Gtk::Label.new("大分"), true, true, 0 ) box.pack_start(box3) w.show_all Gtk.main

(a) 実行結果

(b) (a) のように表示されたあと、ウインドウのサイズを大きくした結果.expand = true の場合,上詰め,左詰めは無い.
イベント (event)
ウインドウを閉じたときプログラムが終了する,というときの決まり文句.
w.signal_connect('delete_event') do Gtk.main_quit false end
ラベル (label)
Ruby-GNOME2 で,色、大きさ等を指定してラベルを作る手順は次の通り.
- 「GTK::Lable.new」でオブジェクトを作り,
- 「Gtk::Label#markup」で文字列(表示する文字列とスタイルを記述した HTML)
- 「Gtk::Box#pack_start」あるいは「Gtk::Box#pack_end」で配置
* サンプルプログラムのソースコード
#! ruby -Ku # -*- coding: utf-8 require 'gtk2' def pack_start_label(box, str, markup, expand, fill, padding) s = Gtk::Label.new s.markup = markup.sub("TEXT", str) box.pack_start( s, expand, fill, padding ) end w = Gtk::Window.new w.set_title "Form" w.signal_connect('delete_event') do Gtk.main_quit false end box = Gtk::VBox.new(false, 10) w.add(box) style1 = %Q[<u><span foreground="red" background="white" size="x-large" style="italic">TEXT</span></u>] box2 = Gtk::VBox.new(false, 10) box.add(box2) pack_start_label(box2, "食べ物", style1, false, false, 0) pack_start_label(box2, "飲み物", style1, false, false, 0) pack_start_label(box2, "デザート", style1, false, false, 0) box.pack_start(box2) box3 = Gtk::HBox.new(false, 10) box.add(box3) pack_start_label(box3, "福岡", style1, false, false, 0) pack_start_label(box3, "大分", style1, false, false, 0) box.pack_start(box3) w.show_all Gtk.main
* サンプルプログラムの実行結果(例)

セパレータ (separator)
セパレータ
- 下記のメソッドでオブジェクトを作り,
- 横のセパレータ: Gtk::HSeparator.new
- 縦のセパレータ: Gtk::VSeparator.new
- Gtk::Box#pack_start」あるいは「Gtk::Box#pack_end」で配置
* サンプルプログラムのソースコード
#! ruby -Ku # -*- coding: utf-8 require 'gtk2' def pack_start_label(box, str, markup, expand, fill, padding) s = Gtk::Label.new s.markup = markup.sub("TEXT", str) box.pack_start( s, expand, fill, padding ) end def pack_start_v_separator(box, expand, fill, padding) s = Gtk::VSeparator.new box.pack_start( s, expand, fill, padding ) end def pack_start_h_separator(box, expand, fill, padding) s = Gtk::HSeparator.new box.pack_start( s, expand, fill, padding ) end w = Gtk::Window.new w.set_title "Form" w.signal_connect('delete_event') do Gtk.main_quit false end box = Gtk::VBox.new(false, 10) w.add(box) style1 = %Q[<span foreground="black" size="x-large">TEXT</span>] box2 = Gtk::VBox.new(false, 10) box.add(box2) pack_start_label(box2, "食べ物", style1, false, false, 0) pack_start_label(box2, "飲み物", style1, false, false, 0) pack_start_label(box2, "デザート", style1, false, false, 0) pack_start_h_separator(box2, false, false, 0) box.pack_start(box2) box3 = Gtk::HBox.new(false, 10) box.add(box3) pack_start_label(box3, "福岡", style1, false, false, 0) pack_start_v_separator(box3, false, false, 0) pack_start_label(box3, "大分", style1, false, false, 0) box.pack_start(box3) w.show_all Gtk.main
* サンプルプログラムの実行結果(例)
spacing の値を 0 よりも大きくしているので,下図での縦線にすき間があく.

ラジオボタン (radio button)
- Ruby-GNOME2 : ラベル名(文字列)を引数とする.
- eRuby : ラベル名(文字列)と値(文字列)を指定
* サンプルプログラムのソースコード
#! ruby -Ku # -*- coding: utf-8 require 'gtk2' require 'pp' class Form def initialize @@table = Hash.new end def register(key, value) # key と value を登録する @@table[key] = value # 「print_info」はデバッグ用(不要なら消しても構わない) print_info return false end def insert_remove(key, value, active) if active # 登録から外す if @@table[key].member?(value) @@table[key].delete(value) else # 無いのに外そうとしている print "error in Form 002" end else # 登録する if @@table.key?(key) # すでに key がある場合 if @@table[key].member?(value) # 二重登録なのでエラー print "error in Form 001" end @@table[key].add(value) else @@table[key] = Set.new([value]) end end end def print_info File.open("log", "w") do |f| @@table.each_pair do |key, value| f.puts "#{key}, #{value}" end end end end def pack_start_label(box, str, markup, expand, fill, padding) s = Gtk::Label.new s.markup = markup.sub("TEXT", str) box.pack_start( s, expand, fill, padding ) end def pack_start_v_separator(box, expand, fill, padding) s = Gtk::VSeparator.new box.pack_start( s, expand, fill, padding ) end def pack_start_h_separator(box, expand, fill, padding) s = Gtk::HSeparator.new box.pack_start( s, expand, fill, padding ) end class RadioButtonGroupManager def initialize @@table = Hash.new end def lookup(attribute_name) # すでにある attribute_name で radio_button が登録済みならば、その radio_button を返す. if @@table.key?(attribute_name) return @@table[attribute_name] else return nil end end def register(attribute_name, radio_button) # attribute_name を key として radio_button を登録。 if @@table.key?(attribute_name) # 登録済みのでなにもしない return else @@table[attribute_name] = radio_button return end end end def pack_start_radio_button(box, form, mgr, attribute_name, str, value, active, expand, fill, padding) # active, exapnd, fill, padding は Ruby-GNOME2 の機能 g = mgr.lookup( attribute_name ) if g.nil? # グループの中の初めてのラジオボタン s = Gtk::RadioButton.new(str) mgr.register( attribute_name, s ) else # グループの中の2つ目以降のラジオボタン s = Gtk::RadioButton.new(g, str) end s.active = active box.pack_start( s, expand, fill, padding ) s.signal_connect('button_press_event') do form.register(attribute_name, value) end end w = Gtk::Window.new w.set_title "Form" w.signal_connect('delete_event') do Gtk.main_quit false end box = Gtk::VBox.new(false, 10) w.add(box) mgr = RadioButtonGroupManager.new form = Form.new style1 = %Q[<span foreground="black" size="x-large">TEXT</span>] # パッキング・ボックス (packing box) box1 = Gtk::HBox.new(false, 10) pack_start_label(box1, "3", style1, false, false, 0) pack_start_v_separator(box1, false, false, 0) box12 = Gtk::VBox.new(false, 10) box13 = Gtk::HBox.new(false, 10) pack_start_label(box13, "旅行の目的", style1, false, false, 0) pack_start_label(box13, "(必須)", style1, false, false, 0) box12.pack_start(box13) pack_start_h_separator(box12, false, false, 0) box14 = Gtk::VBox.new(false, 10) box15 = Gtk::HBox.new(false, 10) pack_start_radio_button(box15, form, mgr, "旅行の目的", "仕事", "仕事", false, false, false, 0) pack_start_radio_button(box15, form, mgr, "旅行の目的", "観光", "観光", false, false, false, 0) pack_start_radio_button(box15, form, mgr, "旅行の目的", "イベント", "イベント", false, false, false, 0) box14.pack_start(box15) pack_start_radio_button(box14, form, mgr, "旅行の目的", "なし", "なし", false, false, false, 0) pack_start_radio_button(box14, form, mgr, "旅行の目的", "その他", "その他", false, false, false, 0) box12.pack_start(box14) box1.pack_start(box12) box.pack_start(box1) w.show_all Gtk.main
* サンプルプログラムの実行結果(例)

* その他の実行例(かきかけ)


チェックボタン (check button)
- Ruby-GNOME2 : ラベル名(文字列),チェックの有無(ブール値)を引数とする.
- eRuby : ラベル名(文字列),チェックの有無(ブール値)を指定
* サンプルプログラムのソースコード
#! ruby -Ku # -*- coding: utf-8 require 'gtk2' require 'pp' require 'set' class Form def initialize @@table = Hash.new end def register(key, value) # key と value を登録する @@table[key] = value # 「print_info」はデバッグ用(不要なら消しても構わない) print_info return false end def insert_remove(key, value, active) if active # 登録から外す if @@table[key].member?(value) @@table[key].delete(value) else # 無いのに外そうとしている print "error in Form 002" end else # 登録する if @@table.key?(key) # すでに key がある場合 if @@table[key].member?(value) # 二重登録なのでエラー print "error in Form 001" end @@table[key].add(value) else @@table[key] = Set.new([value]) end end print_info return false end def print_info File.open("log", "w") do |f| @@table.each_pair do |key, value| f.puts "#{key}" value.each do |e| f.puts e end end end end end def pack_start_label(box, str, markup, expand, fill, padding) s = Gtk::Label.new s.markup = markup.sub("TEXT", str) box.pack_start( s, expand, fill, padding ) end def pack_start_v_separator(box, expand, fill, padding) s = Gtk::VSeparator.new box.pack_start( s, expand, fill, padding ) end def pack_start_h_separator(box, expand, fill, padding) s = Gtk::HSeparator.new box.pack_start( s, expand, fill, padding ) end def pack_start_check_button(box, form, attribute_name, str, value, active, expand, fill, padding) # active, exapnd, fill, padding は Ruby-GNOME2 の機能 # ラジオボタンのときのような「グループ」はない s = Gtk::CheckButton.new(str) s.active = active box.pack_start( s, expand, fill, padding ) s.signal_connect('button_press_event') do form.insert_remove(attribute_name, value, s.active?) end end w = Gtk::Window.new w.set_title "Form" w.signal_connect('delete_event') do Gtk.main_quit false end box = Gtk::VBox.new(false, 10) w.add(box) form = Form.new style1 = %Q[<span foreground="black" size="x-large">TEXT</span>] # パッキング・ボックス (packing box) box1 = Gtk::HBox.new(false, 10) pack_start_label(box1, "4", style1, false, false, 0) pack_start_v_separator(box1, false, false, 0) box22 = Gtk::VBox.new(false, 10) box23 = Gtk::HBox.new(false, 10) pack_start_label(box23, "美味しかった食べ物", style1, false, false, 0) pack_start_label(box23, "(必須)", style1, false, false, 0) box22.pack_start(box23) pack_start_h_separator(box22, false, false, 0) box24 = Gtk::VBox.new(false, 10) box25 = Gtk::HBox.new(false, 10) pack_start_check_button(box25, form, "美味しかった食べ物", "明太子", "明太子", false, false, false, 0) pack_start_check_button(box25, form, "美味しかった食べ物", "博多ラーメン", "博多ラーメン", false, false, false, 0) pack_start_check_button(box25, form, "美味しかった食べ物", "もつ鍋", "もつ鍋", false, false, false, 0) pack_start_check_button(box25, form, "美味しかった食べ物", "水たき", "水たき", false, false, false, 0) pack_start_check_button(box25, form, "美味しかった食べ物", "地鶏", "地鶏", false, false, false, 0) box24.pack_start(box25) pack_start_check_button(box24, form, "美味しかった食べ物", "全て美味しい", "全て美味しい", false, false, false, 0) pack_start_check_button(box24, form, "美味しかった食べ物", "その他", "その他", false, false, false, 0) box22.pack_start(box24) box1.pack_start(box22) box.pack_start(box1) w.show_all Gtk.main

* eRuby の例

ブーレアン・チェックボタン (boolean check button)
書きかけ
セレクトメニュー (select menu)
書きかけ



1行テキスト (text)
書きかけ
テキストエリア (textarea)
書きかけ
カレンダー (calendar)
サンプルプログラムをありがたく拝借.

require 'gtk2' cal = Gtk::Calendar.new w = Gtk::Window.new w.add(cal).show_all.signal_connect('delete_event') do Gtk::main_quit end date = Time.new cal.select_month(date.month, date.year) cal.select_day(date.day) cal.mark_day(date.day) #cal.clear_marks cal.display_options(Gtk::Calendar::SHOW_HEADING | Gtk::Calendar::SHOW_DAY_NAMES | Gtk::Calendar::WEEK_START_MONDAY) year, month, day = cal.date puts "this is #{month} #{day}, #{year}" cal.signal_connect('day_selected') do year, month, day = cal.date puts "selected day: #{day}" end cal.signal_connect('month_changed') do year, month, day = cal.date puts "changed month: #{month}" end cal.signal_connect('day_selected_double_click') do year, month, day = cal.date puts "dclicked day: #{day}" end cal.signal_connect('prev_month') do year, month, day = cal.date puts "prev month: #{month}" end cal.signal_connect('next_month') do year, month, day = cal.date puts "next_month: #{month}" end cal.signal_connect('prev_year') do year, month, day = cal.date puts "prev_year: #{year}" end cal.signal_connect('next_year') do year, month, day = cal.date puts "next year: #{year}" end Gtk::main
アジャスタ (adjuster)
書きかけ
Ruby-GNOME2 では、ボックスパッキングとテーブルパッキングを使用
「その他」をチェックしたときだけ入力欄が出現する(下図),というようなことは今度の課題
