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 では、ボックスパッキングとテーブルパッキングを使用
「その他」をチェックしたときだけ入力欄が出現する(下図),というようなことは今度の課題