金子邦彦研究室プログラミングRuby プログラミングRuby-GNOME2 を用いたフォームのデザイン

Ruby-GNOME2 を用いたフォームのデザイン

フォームのデザインについて、次のことを例を使って説明する.

Ruby-GNOME2 なので,漢字コードとして utf-8 を使うことにします.

※ 画面遷移,フォーム部品の配置等に関する設計については,この Web ページの範囲外とします.

※ Ruby-GNOME2 のインストール手順は, 「Windows で Ruby-GNOME2 のビルドとインストール」の Web ページ, 「Linux で Ruby-GNOME2 のビルドとインストール」のページで説明している.

説明に使うフォームの例

[image]

パッキングボックス (packing box)

パッキングの例, 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

[image]
(a) 実行結果

[image]
(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

[image]
(a) 実行結果

[image]
(b) (a) のように表示されたあと、ウインドウのサイズを大きくした結果.expand = true の場合,上詰め,左詰めは無い.

イベント (event)

ウインドウを閉じたときプログラムが終了する,というときの決まり文句.

w.signal_connect('delete_event') do
  Gtk.main_quit
  false
end

ラベル (label)

Ruby-GNOME2 で,色、大きさ等を指定してラベルを作る手順は次の通り.

  1. 「GTK::Lable.new」でオブジェクトを作り,
  2. 「Gtk::Label#markup」で文字列(表示する文字列とスタイルを記述した HTML)
  3. 「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

■ サンプルプログラムの実行結果(例)

[image]

セパレータ (separator)

セパレータ

  1. 下記のメソッドでオブジェクトを作り,
  2. 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 よりも大きくしているので,下図での縦線にすき間があく.

[image]

ラジオボタン (radio button)

■ サンプルプログラムのソースコード

#! 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

■ サンプルプログラムの実行結果(例)

[image]

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

[image]

[image]

チェックボタン (check button)

■ サンプルプログラムのソースコード

#! 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

[image]

■ eRuby の例

[image]

ブーレアン・チェックボタン (boolean check button)

書きかけ

セレクトメニュー (select menu)

書きかけ

[image]

[image]

[image]

1行テキスト (text)

書きかけ

テキストエリア (textarea)

書きかけ

カレンダー (calendar)

サンプルプログラムをありがたく拝借.

[image]
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 では、ボックスパッキングとテーブルパッキングを使用

「その他」をチェックしたときだけ入力欄が出現する(下図),というようなことは今度の課題

[image]