[ruby-gnome2-doc-cvs] [Hiki] update - ウインドウ

Back to archive index

ruby-****@lists***** ruby-****@lists*****
2003年 5月 26日 (月) 22:39:15 JST


-------------------------
REMOTE_ADDR = 210.249.193.205
REMOTE_HOST = 
        URL = http://ruby-gnome2.sourceforge.jp/?%A5%A6%A5%A4%A5%F3%A5%C9%A5%A6
-------------------------

-------------------------
= ウインドウ
まずはウインドウのみを表示するためのGtk::Windowを説明します。他のほとんどのウィジェットはこのGtk::Windowの上に追加していく形になります。

== 基本的な使い方
  require 'gtk2'
  
  Gtk.init
  
  window = Gtk::Window.new
  window.set_title("Test")
  window.set_default_size(300,200)
  window.show_all

  Gtk.main

--- Gtk.init(argv = ARGV)
    ライブラリを初期化します。必ず、他のRuby/GTKのクラス・メソッドを呼び出す前に呼び出す必要があります。

--- Gtk::Window.new(type = Gtk::Window::TOPLEVEL)
    Gtk::Windowオブジェクトを生成します。この段階ではまだ表示されません。引数は以下のWindowTypeを指定できます。ウインドウマネージャによってはウインドウ飾り等が変わります。
   * Gtk::Window::TOPLEVEL - 通常のウインドウ
   * Gtk::Window::POPUP - ポップアップ用のウインドウ(ウインドウ飾りなし)

--- Gtk::Window#title=(title)
--- Gtk::Window#set_title(title)
    ウインドウのタイトルを設定します。ウインドウマネージャによって表示のされ方が違いますが、平均的にはウインドウの一番外側に表示されます。

--- Gtk::Window#set_default_size(width, height)
    ウインドウのデフォルト(初期表示時の)サイズを設定します。

--- Gtk::Widget#show_all
    実際に画面表示を行います。Gtk::Widget#show_all, Gtk::Widget#showの2種類があります。前者はウインドウを含め全ての子ウィジェットの表示を行い、後者はこのウインドウのみの表示を行います。

--- Gtk.main
    ここからイベントループ(無限ループ)に入ります。イベントループの中から各種のイベントをディスパッチします(イベント毎に処理に処理を振り分けます)。一回Gtk.mainでイベントループに入ると、Gtk.main_quitが呼び出されるまでイベントループから抜け出せません。

== 子ウィジェットを追加する
ウインドウを生成したら次はウィジェットを追加していきます。Gtk::Windowには基本的に1つしかウィジェットを追加できません。実際は、ウインドウにコンテナウィジェット(Gtk::VBoxなど)を追加してそれに対してウィジェットを追加するという感じでどんどんウィジェットを追加していきます。ここではただ単純にGtk::Buttonを追加してみます。

  require 'gtk2'

  Gtk.init
  button = Gtk::Button.new("OK?")
  window = Gtk::Window.new
  window.add(button)
  window.show_all

  Gtk.main

--- Gtk::Container#add(widget)
    ウィジェットを追加します。

== 表示位置を指定する
スクリーン上のどこに表示するか、その表示位置を指定します。

  require 'gtk2'

  Gtk.init
  button = Gtk::Button.new("OK?")
  window = Gtk::Window.new
  window.set_title("Test")
  window.set_window_position(Gtk::Window::POS_CENTER)
  window.show_all

  Gtk.main

--- Gtk::Window#window_position=(pos)
--- Gtk::Window#set_window_position(pos)
    ポジションを指定します。
   * Gtk::Window::POS_NONE - 指定なし(default)
   * Gtk::Window::POS_CENTER - 画面中央
   * Gtk::Window::POS_MOUSE - マウスの位置
   * Gtk::Window::POS_CENTER_ALWAYS - 常に中央(サイズを変更したりしても極力中央に移動しようとします)
   * Gtk::Window::POS_CENTER_ON_PARENT - 親ウインドウの中央

== ジオメトリ情報を指定する
ユーザによってどのようにそのウインドウがリサイズすることができるかといった情報(Gdk::Geometry ジオメトリヒント)を指定します。

  require 'gtk2'

  Gtk.init
  geometry = Gdk::Geometry.new
  geometry.set_min_width(100)
  geometry.set_min_height(100)
  geometry.set_max_width(600)
  geometry.set_max_height(600)
  geometry.set_width_inc(50)
  geometry.set_height_inc(100)

  mask = Gdk::Window::HINT_MIN_SIZE |
         Gdk::Window::HINT_MAX_SIZE | Gdk::Window::HINT_RESIZE_INC

  button = Gtk::Button.new("OK?")
  window = Gtk::Window.new
  window.add(button)
  window.set_geometry_hints(button, geometry, mask)

  window.show_all
  Gtk.main  


--- Gtk::Window#set_geometry_hints(widget, geometry, mask)
    ジオメトリ情報を設定します。
    * widget - 対象のGtk::Widget
    * geometry - Gdk::Geometry。ここでは、最小・最大サイズ、それから幅・高さ共に増減分(ウインドウをマウスで大きく・小さくする際に、一度にどれだけ変化するか)を指定しています。
    * mask - この値は上記でも示しているように、実際Gdk::Geometryで使用する(ジオメトリのヒントとして認識させたい)項目(Gdk::Window::HINT_*)を|(パイプ)で論理和を取っていきます。上記例ですとポジション・最小・最大・リサイズの増減分がジオメトリの対象となります。例えば、ここでGdk::Window_HINT_MIN_SIZEを除いてみると、set_min_{width|height}で指定した情報が認識されなくなります。

== ウインドウの閉じるボタンで画面を閉じる(メインループを抜ける場合)
ウインドウマネージャによって表示場所などは一概に言えないのですが、大抵のウインドウはウインドウ枠の部分に「閉じる」ボタンがあります(×ボタンが多いようです)。で、このボタンを閉じる際にきちんと後処理をしないと正常に終了してくれません(ウインドウは表示されていないがメインループからは抜けていないため、プロセスは残ってしまう)。そこで、ここでは「閉じる」ボタンがクリックされたのと同タイミングでメインループから抜けてみます。

  require 'gtk2'
 
  Gtk.init
  window = Gtk::Window.new
 
  window.signal_connect("delete-event") do 
    p "DELETE EVENT"   #(1)
    false
  end
 
  window.signal_connect("destroy") do 
    p "DESTROY EVENT"  #(2)
    Gtk.main_quit  
  end
 
  window.show_all
 
  p "Start"
  Gtk.main             #(3)
  p "End"

この場合、ウインドウマネージャの「閉じる」ボタン → (1)(ここでfalseを返した場合) → (2) という風に呼び出されます。通常は(2)でそのままGtk.main_quitを呼び出しても良いのですが、Gtk::Window::SIGNAL_DESTROYのイベントハンドラの中でGtk.main_quitを呼び出した方がお行儀が良いんじゃないかな。まぁ、どちらかを使えば良いと言うことで。

--- "destroy"
    "destroy"シグナル。このシグナルが発生するのは、このウインドウでGtk::Widget#destroyを読んだ場合かあるいは、"delete-event"コールバックがfalseを返した場合です。

--- "delete-event"
    ウインドウがウインドウマネージャから、普通は'close'オプション、あるいはタイトルバーの「閉じる」ボタンによって"delete-event"シグナルを与えられた場合に発生します。

--- Gtk.main_quit
    Gtk.mainループを抜けます。この場合、Gtk.mainループが(3)の部分になりますので、このメソッドが呼ばれたときには(3)より後が実行されます(Endを表示してプログラムは終了する)。

== ウインドウの閉じるボタンで画面を閉じる(ウインドウを隠す場合)
次に、ウインドウは閉じるけどそのウインドウは破壊(destroy)せずに隠すだけにして、使い回す例をあげてみます。1つのウインドウではうまく説明できないので、2つのウインドウを使って説明します。

  require 'gtk2'

  Gtk.init
 
  window = Gtk::Window.new
  window2 = Gtk::Window.new

  window2.signal_connect("delete-event") do 
    p "DELETE EVENT"
    window2.hide
    true
  end

  button = Gtk::Button.new("Create New Window")
  button.signal_connect("clicked") do
    window2.show_all
  end

  window.add(button)
  window.show_all

  Gtk.main

ここでのポイントは、"delete-event"のブロックの中でtrueを返すところです。これがfalseだとdestroyイベントが発生してしまいます(そしてwindow2自体が破棄される)。

--- Gtk::Widget#hide
    ウィジェットを隠します。インスタンス自体は破棄しません。インスタンスも破棄する場合はGtk::Object#destroyを使います。

ちなみに、"delete-event"のブロックをコメントアウトして再度実行してみてください。
一度ウインドウをクローズしてから再度ボタンをクリックしてウインドウを表示しようとするとdestroyed GLib::Objectというエラーになってしまいます。

アプリケーションを作る際は、このようにwindow2の生成は1度しかしないで使い回すという方法と、上の例で言うと"clicked"のブロックの中で毎回window2を生成する場合の2つの実装方法があります。個人的には、リソースに余裕がある場合は、後者の方が読みやすいと思います。
ちょっと説明したい内容がずれるのですが、そのような実装例を次に示しますので見比べてみてください。

== モーダルウインドウを作る
2つ目のウインドウを生成した際に、1つ目のウインドウへのユーザのアクセスを禁止したい場合がありますが、そのような場合はウインドウをモーダルにします。

  require 'gtk2'
 
  Gtk.init
  window1 = Gtk::Window.new
 
  button = Gtk::Button.new("Create New Window")
  button.signal_connect("clicked") do
    window2 = Gtk::Window.new
    window2.set_modal(true)
    window2.show_all
  end
 
  window1.add(button)
  window1.show_all
 
  Gtk.main

--- Gtk::Window#modal=(modal)
--- Gtk::Window#set_modal(modal)
    ウインドウをモーダルにするかどうかを指定します。
    * modal - モーダルにする場合はtrue,モーダルにしない場合はfalse(デフォルト)

== サブウインドウを常にメインウインドウの手前に表示する
サブウインドウを常にメインウインドウの手前に表示してみます。Gtk::Window#set_modal()と組み合わせて使う場合が多いと思いいます。

  require 'gtk2'

  Gtk.init
  window1 = Gtk::Window.new

  button = Gtk::Button.new("Create New Window")
  button.signal_connect("clicked") do
    window2 = Gtk::Window.new
    window2.set_transient_for(window1)
    window2.show_all
  end

  window1.add(button)
  window1.show_all

  Gtk.main

--- Gtk::Window#transient_for=(parent)
--- Gtk::Window#set_transient_for(parent)
    ウインドウを指定したウインドウよりも常に手前に表示します。
    * parent - 親ウインドウ(Gtk::Window)。常にここで指定したウインドウより手前に表示されます。

== 指定ウィジェットにフォーカスをあてる
ここでは3つのボタンを生成して3つ目のウインドウにフォーカスをあててみます。ちょっとわかりづらいかな...。

  require 'gtk2'
  
  Gtk.init
  window = Gtk::Window.new
  
  button1 = Gtk::Button.new("Button1")
  button2 = Gtk::Button.new("Button2")
  button3 = Gtk::Button.new("Button3")
  
  window.add(Gtk::VBox.new.add(button1).add(button2).add(button3))
  window.set_focus(button3)
  window.set_default_size(100,100)
  window.show_all
  
  Gtk.main

--- Gtk::Window.focus=(widget)
--- Gtk::Window.set_focus(widget)
    指定したウィジェットにフォーカスをあてます。
    * widget - フォーカスをあてるウィジェット(Gtk::Widget)

== ウインドウクラスヒントを指定する
クラスヒントは、ウィンドウマネージャがそのウィンドウを判別できるようにするためのIDみたいなものです。
大部分のウインドウマネージャは、クラスヒントを用いてウインドウを区別します。例えば、私が使っているsawfishではウインドウ毎にウインドウ枠の属性や大きさ、位置を変更し、それらを保存することができます。
ここでは、3つのウインドウにクラスヒントを指定してみます。
このサンプルを起動しただけでは何も起きませんが、例えば、sawfishの場合、ウインドウの大きさや位置などを変更した後で、ウインドウ枠についてるメニューから「履歴」→「位置を記憶」「大きさを記憶」「属性を記憶」等を選択した後でこのサンプルを再度起動してみると、クラスヒントを指定した場合とそうでない場合での違いがわかると思います。

  require 'gtk2'

  Gtk.init
  window1 = Gtk::Window.new.set_title("Window1")
  window2 = Gtk::Window.new.set_title("Window2")
  window3 = Gtk::Window.new.set_title("Window3")

  window1.set_wmclass("test1", "Ruby/GTK Test")
  window2.set_wmclass("test2", "Ruby/GTK Test")
  window3.set_wmclass("test3", "Ruby/GTK Test")

  window1.show
  window2.show
  window3.show

  Gtk.main

--- Gtk::Window#set_wmclass(wmclass_name, wmclass_class)
    ウインドウクラスヒントを指定します。このメソッドはそのウインドウがrealizeされる前(例えば、showの前)に呼び出される必要があります。
    * wmclass_name - アプリケーション(例えばメインウィンドウやダイアログ等)のウインドウの名称を指定します。
    * wmclass_class - 通常はアプリケーション名を指定します。


=end





ruby-gnome2-cvs メーリングリストの案内
Back to archive index