Ruby/Tk でマルチスレッドプログラム
Ruby/Tk でウィンドウ上のオブジェクトを定期的に更新するデモプログラムを作ってみました。
独立したスレッドからオブジェクトをそれぞれ更新するようにしてみます。試しに時計を表示させてみます。
require 'tk' # ウィジェットの作成 button = TkButton.new(text: "exit", command: proc {p "exit"; exit}) label1 = TkLabel.new(text: "", font: ['',24]) label2 = TkLabel.new(text: "", font: ['',24]) label3 = TkLabel.new(text: "") label1.pack label2.pack label3.pack button.pack Tk.mainloop
これで枠組みだけできました。
こんどは時計表示を更新する関数を作成
# カレンダーを更新 def update_calendar(label) now = Time.new label.configure(text: sprintf("%04d 年 %02d 月 %02d 日", now.year, now.month, now.day)) end # 時計を更新 def update_clock(label) now = Time.new label.configure(text: sprintf("%02d : %02d : %02d", now.hour, now.min, now.sec)) end
この関数を呼び出すために、Tk.mainloop の前に以下の記述を追加します。
update_calendar(label1) update_clock(label2)
時間が表示されました。
今度はこの時計を定期的に更新します。上記の2行をこのように書き換えます。
# 要素ごとにスレッドを立てて更新する Thread.new { while true update_calendar(label1) sleep(60) end } Thread.new { while true update_clock(label2) sleep(1) end }
Thread.new {} で並列に実行されるサブスレッドを作成します。スレッドが実行するのは {} の中の while true ~ end の無限ループ。
カレンダー表示の更新の後、 sleep(60) で 60 秒間待つため、1分間に1回カレンダーは更新されますが、時計の方は 1秒に一回更新されるはずです。
全部のコードはこんな感じ
require 'tk' # カレンダーを更新 def update_calendar(label) now = Time.new label.configure(text: sprintf("%04d 年 %02d 月 %02d 日", now.year, now.month, now.day)) end # 時計を更新 def update_clock(label) now = Time.new label.configure(text: sprintf("%02d : %02d : %02d", now.hour, now.min, now.sec)) end # ウィジェットの作成 button = TkButton.new(text: "exit", command: proc {p "exit"; exit}) label1 = TkLabel.new(text: "", font: ['',24]) label2 = TkLabel.new(text: "", font: ['',24]) label3 = TkLabel.new(text: "") # ウィジェットの配置 label1.pack label2.pack label3.pack button.pack # 要素ごとにスレッドを立てて更新する Thread.new { while true update_calendar(label1) sleep(60) end } Thread.new { while true update_clock(label2) sleep(1) end } Tk.mainloop
これで、時計を毎秒更新する一方、カレンダーは毎分更新するマルチスレッドプログラムができました。