Ruby/Tk - FrontPage  Index  Search  Changes  PageRank  RSS  Login

Rubyのソースに添付のサンプル

Rubyのソースアーカイブに添付されているサンプルスクリプトです. Rubyのソースツリーにおいて,ext/tk/sampleディレクトリの下に置かれています. あまり御存知でない方もいらっしゃるようなのですが,単純なデモだけでなく, ウィジェットクラスライブラリとして使えるものなども含んでおり, 有用と言えるものです.

ですがRubyのバイナリ配布パッケージには,これらのサンプルスクリプトを含めていない(ソースの一部と判断されて除外されている)ものもあります. その場合は,Rubyのソースアーカイブを入手して,抜き出してください.

ウィジェットデモ (WidgetDemo)

  • スクリプトファイル:demo-jp/widget, demo-en/widget

Tcl/Tkに添付されているウィジェットデモのRuby/Tk版です. ウィジェットデモは,単なるデモスクリプトではなく,Ruby/Tkを学習するためのツールでもあります. demo-jpが日本語版,demo-enが英語版となっています.これらは表示メッセージの違いにすぎないので,英語版で日本語を使うことも問題ないはずです. ファイル名に拡張子が付いていないので,Windowsで利用される方はコマンドを指定して実行するか,ファイル名を変更して拡張子.rbwを付けてください.

ウィジェットデモを起動すると,デモの一覧を示すテキストウィジェットを持ったウィンドウが開きます.各デモ名にはバインディングがなされており,マウスでクリックすることで,そのデモを起動することができます.

起動されたデモには「コード参照」というボタンがあると思います.そのボタンをクリックすれば,新たにウィンドウが開いて現在実行中のデモのソースコードを見ることができます.ソースコードの表示にはテキストウィジェットを用いており,実際に編集することが可能です.

編集した後にソースコード表示ウィンドウの「再実行」ボタンを押せば,編集した内容での実行が行われます.これにより,デモのソースを参照しつつ,変更を実際に試しながらRuby/Tkを学ぶことができるわけです.編集はソースコード表示ウィンドウの中だけでのことで,ディスク上のファイルには影響しませんので心置きなく書き換えてみてください.変更しすぎて原形がわからなくなってしまった場合は,デモの「コード参照」ボタンを再度クリックしてください.編集結果をすべて破棄してディスク上のファイルを再度読み込むことができます.

デモ兼ライブラリとして使えるもの

このグループには,requireで読み込むことで ウィジェットクラス/モジュールライブラリとして使えるものを挙げておきます. なお,スクリプトファイルを直接実行すれば, そのクラス/モジュールのデモとして動きます.

Tk::RbWidget::Editable_Listboxクラス

( 旧いファイルでは Editable_Listboxクラスとなっています.)

  • スクリプトファイル:editable_listbox.rb

キーボードから項目を編集することができる listtbox widget です.

例えば,項目をダブルクリックすると,その項目の位置にその項目の 内容を編集できる entry box が現れます. もちろん,編集結果は listbox に反映されます.

Tk::RbWidget::ScrollFrameクラス

( 旧いファイルでは TkScrollFrameクラスとなっています.)

  • スクリプトファイル:scrollframe.rb

スクロール可能なビューウィンドウ (フレームの一部を切り取って見るためのもの) を持った frame widget です.

例えば,ボタンがたくさん並んだツールバーを想像してみてください. ツールバーはウィンドウサイズに比べてかなり長いものとします. そのような場合には,ツールバーをスクロールさせて表示するようにしたくなるかもしれません. このウィジェットクラスを使えばそうしたことが簡単に実装できます.

Tk::RbWidget::HBox,HLBox,HRBox,VBox,VTBox,VBBoxクラス

( 旧いファイルでは Tk::HBox,HLBox,HRBox,VBox,VTBox,VBBoxクラスとなっています.)

  • スクリプトファイル:tkalignbox.rb

ウィンドウサイズが変わっても,並んでいるウィジェット(例えば文字列 の長さやフォントの高さが異なるボタンの並び)のそれぞれの幅や高さを 同じに保ちつづけるというのは少々難しいものです. これらのウィジェットクラスは,そうしたことを簡単に実現できるようにするための一種の frame widget です.

例えば,ボタン b1, b2, b3, b4, ... に対して Tk::RbWidget::HLBox.new(parent).add(b1, b2, b3, b4, ...) などとすると, 各ボタンが HLBox フレームに左詰めで配置されます. その際,各ボタンの大きさが違っていても,すべて同じになるように調整されます. ウィンドウの大きさが変更されて HLBox ウィジェットのサイズが変更になった場合でも, HLBox ウィジェットのサイズに合わせてそれぞれのボタンが同じ大きさとなるように保ちつづけます.

それぞれのウィジェットクラスは詰め込む向きが違います. HLBox (== HBox)は横方向左詰め,HRBoxは横方向右詰め, VTBox (== VBox)は縦方向上詰め,VBBoxは縦方向下詰めです.

Tk::RbWidget::BalloonHelpクラス

( 旧いファイルでは TkBalloonHelpクラスとなっています.)

  • スクリプトファイル:tkballoonhelp.rb

親ウィジェットにバルーンヘルプを加えます. もちろん,表示するメッセージやバルーンヘルプが表示されるまでの 時間などを制御することが可能です. 表示の際の hook メソッドも定義できますので, listbox の項目ごとに異なるメッセージを出力するなどということも可能です.

Tk::RbWidget::AutoScrollListboxクラス

( 旧いファイルでは TkAutoScrollListboxクラスとなっています.)

  • スクリプトファイル:tkcombobox.rb

自動スクロールタブ付きの listbox です. タブはその方向に表示範囲外の項目が存在する場合だけに現れます. タブの上でマウスを動かさないようにしていれば,その方向に自動的にスクロールします.

このスクリプトファイルには,次のTk::RbWidget::Comboboxクラスも含んでいます.

Tk::RbWidget::Comboboxクラス

( 旧いファイルでは TkComboboxクラスとなっています.)

  • スクリプトファイル:tkcombobox.rb

選択リストに Tk::RbWidget::AutoScrollListbox ウィジェット を使った combobox widget です.

Tk::ScrollbarCompositeモジュール

( 旧いファイルでは,このモジュールはスクリプトファイルに含まれていません.)

  • スクリプトファイル:tktextframe.rb

このサンプルスクリプトで動作するのは, スクロールバー付きのテキストウィジェットであるTkTextFrameクラスのデモなのですが, 同クラスの実装の中核となっているのがTk::ScrollbarCompositeモジュールです. このモジュールは,スクロール可能なウィジェットにスクロールバーを付与した複合ウィジェットを 作る際の手助けとなるものです.

例えば,

  class ScrListbox < Tk::Listbox
    include Tk::ScrollbarComposite
    DEFALUT_HSCROLL = false
    def create_component(keys={})
      Tk::Listbox.new(@frame, keys)
    end
    private :create_component
  end

というようにすることで,縦方向 (Y 方向) のスクロールバー付きの listbox ウィジェットである 復号ウィジェットクラスScrListboxを定義できます. もちろん,ScrListbox.new.pack などというように, 他のウィジェットクラスと同じに扱うことができます.

TkTextIOクラス

  • スクリプトファイル:tktextio.rb

テキストウィジェットをI/Oストリームとして使えるようにしたクラスです. 後述のirbtkw.rbwでも使っています.

一般的な入出力メソッドは使えるようになっているとは思いますが, getcやseek,readのサイズなどは バイト単位ではなく文字単位である点が特殊です. もしかすると逆にそれが嬉しいという場合もあるかもしれません.

少しは使い道があるかもしれないデモスクリプト

このグループには,デモスクリプトではあるものの, もしかしたらほぼそのままに役立てることができるかもしれないもの(^_^;を 挙げておきます.

Ruby/Tk付きのirbコンソール

  • スクリプトファイル:irbtkw.rbw

Tcl/Tkのwishコマンドでは インタラクティブにウィジェットを操作することができますが, これをirbで可能にしたものです ...と言ってしまうと, 「irbを起動したあとでThread.new{Tk.mainloop}の実行で十分」という答えが 返ってくるかもしれません. それで動作に問題ない環境ならいいのですが, Windowsのコマンドプロンプトでirbを動かしている場合などは (少なくとも旧いRubyでは)キーボード入力待ちでスレッドが切り替わらず, うまくインタラクティブに動作させることができません (私自身は確認してはいませんが,比較的新しいバージョンのRubyでは,この問題は解消されたらしいです). "rbw"という拡張子からも連想できるように, Windows環境でもそれなりにバックグラウンドのスレッドが 動作するように対策したものがこのスクリプトです.

このスクリプトでは,通常のコンソールは使用しません. Ruby/Tkのテキストウィジェットを利用して コンソールウィンドウを作成(前述のTkTextIOクラスを参照)し, 通常の irb をその中で動かしています (Tk.mainloopは既にバックグラウンドで動いています). それにより,キーボード入力待ちのために バックグラウンドスレッドにうまく切り替わらないという問題は 回避できるはずです. もちろん標準入出力は普通に使えますので, Windows上でirbでスレッドを使うスクリプトの動作を 試してみようとする際(Ruby/Tkのrootウィンドウが 邪魔かもしれませんが(^_^;)に使ってもらってもいいでしょう.

ただ,少なくともこの項を執筆している現在, このスクリプトはRuby 1.9の一部の環境では動きません. Tcl/Tk自体の制約などの条件により, 一部の環境ではmain thread以外でTk.mainloopを 正常に動かすことができないためです. 申し訳ないのですが,御了承ください.

既存スクリプトのスタイルエンジン対応化

  • スクリプトファイル:ttk_wrapper.rb

TkButtonなどを使って書かれた既存のスクリプトを 強引にTtk拡張を利用して動かすようにするスクリプトです.

Ttk拡張は,以前はTk拡張ライブラリとして, 現在はTcl/Tkの標準ライブラリとして組みこまれたもので, ウィジェットの表示スタイル(テーマ)を 指定(あるいは新たにデザイン)することを 可能にしてくれます (デフォルトのテーマでの概観も, 標準のウィジェットよりは改善されています). ただし,その機能を提供するために ウィジェットのオプションには一部変更が加えられており, それゆえ,標準のTkウィジェットとTtkウィジェットとが 併存する形になっています.

最新のRuby/Tkでは,例えばボタンウィジェットにおいて, 標準のTkウィジェットはTk::Buttonで, TtkウィジェットはTk::Tile::ButtonまたはTtk::Buttonで 指定できるようになっています. 同時に, TkButtonはTk::ButtonまたはTk::Tile::Buttonの別名として定義されており, Tk.default_widget_set=メソッドで切替えることができます. もちろん,使っているウィジェットオプションによっては エラーを生じる可能性がありますが, そこをやや強引にwrapして動かすようにするのが ttk_wrapper.rbスクリプトです.

"ruby ttk_wrapper.rb 既存のスクリプト"とすれば, デフォルトのウィジェットとしてTtk拡張のものを用いるようにして, デフォルトのスタイル(テーマ)で既存のスクリプトを起動してくれます. スタイル(テーマ)を指定したい場合には "ruby ttk_wrapper.rb -r テーマ 既存のスクリプト"としてください. "ruby ttk_wrapper.rb -l"とすれば, 現在の実行環境で利用できるテーマ名の一覧を見ることができます.

カウントダウンタイマー

  • スクリプトファイル:cd_timer.rb

TkRTTimerクラスの利用例の一つです. コマンドライン引数に並べた分単位の時間(実数可)でカウントダウンします. また,指定時間を過ぎた分については赤字でカウントアップします. コマンドライン引数として与える時間の数には特に制限はありません. また,どのような並びで与えても,時間の長さでソートした順に表示されます. (図は "ruby cd_time.rb 0.1 0.2 0.5 1 2 3" で実行した時のものです.)

cd_timer.png

ベルを鳴らす処理はいい加減なものしか付けていませんので, 必要に応じて改良してみてください. ソース中で "idx.times{Tk.bell}" と書いている位置が ベルを鳴らすべきタイミングです (idxはソート後の順で何番目のカウントダウン時刻かを示します). 適当なベル処理を書いて,この位置で呼ぶようにすればいいでしょう.

ただし,ベル処理に時間がかかる場合は要注意です. この処理はタイマーイベントのコールバック処理の中で行っていますから, 時間がかかる処理でブロックしてしまうとタイマーの進行が停止してしまいます. そのような場合はスレッドを生成して処理を任せてしまい, コールバック処理自体はさっさと終了するようにしてください.

(…以下,続く)

Last modified:2010/08/30 19:09:26
Keyword(s):[Ruby/Tk] [Ruby]
References:[Ruby/Tkのサンプルスクリプト]