From: TOYOFUKU Chikanobu Date: 2003-01-19T02:16:03+09:00 Subject: [ruby-list:36965] Re: Gtk.main 豊福です。 少し前の話題ですが 私(豊福) Date: Thu, 5 Dec 2002 15:14:43 +0900 [ruby-list:36671] Re: Gtk.main > Gtk.main と Gtk.main_quit とダイアログとスレッドがごっちゃ > になって混乱しています。整理がついたら改めてフォローしたいと > 思います。 についてやっと整理しました。 (a) Gtk.main はネストしてよい。 (b) ダイアログではボタンが押されるまで他の処理を待たせる ケースが多いがそのときには Gtk.main を使う。 (c) 制御が戻らない重い処理をしているときにウィンドウの再描画 させるには別スレッドを作ってそこで Gtk.main相当の処理を させるしかない。 (d) Gtk.main_quit は一番内側の Gtk.main を抜けろと指示する。 (e) 別スレッドで実行されている Gtk.main にも Gtk.main_quit は 効くようだ。 最後の (e) は試してみた結果からの推測です。 > やりたいことをさらに具体的にいうとまずウィンドウAを出し > ていてそこにつけたメニューから重い処理を実行します。重い処理 > というのは外部コマンドを何回か system(正確には IO.popen)で > 実行しています。そのときに「しばらくお待ちください」ダイアロ > グを出しそのダイアログにはキャンセルボタンがついていてその > ボタンでキャンセルすると重い処理を中断します。ダイアログの > 移動でウィンドウAが expose されたときは再描画します。 > 重い処理が終了したら「しばらくお待ちください」ダイアログを > 「終了しました」ダイアログにします。 結局以下のようなコードにしました。 require 'gtk' class MyDialog < Gtk::Dialog def initialize super set_modal(true) @label = Gtk::Label.new('') vbox.pack_start @label @ok_button = Gtk::Button.new('OK') @ok_button.signal_connect(Gtk::Button::SIGNAL_CLICKED) do Gtk.main_quit hide end action_area.pack_start @ok_button @cancel_button = Gtk::Button.new('CANCEL'); @cancel_button.signal_connect(Gtk::Button::SIGNAL_CLICKED) do print "cancel\n" $cancel = true @label.set_text('wait a moment'); @label.show @cancel_button.hide; @ok_button.hide show end action_area.pack_start(@cancel_button, true, true, 20) end def wait @label.set_text('executing ...'); @label.show @ok_button.hide; @cancel_button.show show Gtk.main end def finish @label.set_text('finished'); @label.show @cancel_button.hide; @ok_button.show show Gtk.main end end button = Gtk::Button.new("start") button.signal_connect(Gtk::Button::SIGNAL_CLICKED) do th = Thread.new { $dia.wait } $cancel = false (0..3).each { |i| break if ($cancel) print "sleep\n" sleep(5) # 重い処理 } Gtk.main_quit th.join $dia.finish end $dia = MyDialog.new win = Gtk::Window.new win.add(button) win.show_all Gtk.main --- 豊福 ttoyofukujp@ybb.ne.jp