非 GUI コードの実行中に Escape キーが押されたかどうかを確認する必要があります。(コードは Python ですが、必要に応じて C を簡単に呼び出すことができます。) コードは、中断されたかどうかを確認するためにときどき呼び出す GUI から関数を受け取りました。問題は、このチェックをどのように実装するかです。
ドキュメントを見ると、gdk_event_peek
これには優れた選択肢のようです。
def _check_esc(self):
event = gtk.gdk.event_peek()
if event is None or event.type not in (gtk.gdk.KEY_PRESS, gtk.gdk.KEY_RELEASE):
return False
return gtk.gdk.keyval_name(event.keyval) == 'Escape'
ただし、これは機能しませんgtk.gdk.event_peek()
。メイン ループが実行されていない場合、返されるイベントは常に None です。に変更してgtk.gdk.display_get_default().peek_event()
も役に立ちません。イベントは X イベント キューにあり、まだ GDK イベント キューに移動されていないと仮定します。ドキュメントには次のように記載されています。
この関数は、ウィンドウ システムからそれ以上のイベントを取得しないことに注意してください。すでに GDK イベント キューに移動されているイベントのみをチェックします。
では、どのようにしてイベントを GDK イベント キューに転送するのでしょうか? 言い換えれば、いつgtk.gdk.peek_event()
イベントを返すのでしょうか? 呼び出しgtk.events_pending()
ても効果はありません。
これをテストするための最小限のプログラムを次に示します。
import gtk, gobject
import time
def code(check):
while 1:
time.sleep(.1)
if check():
print 'interrupted'
return
def _check_esc():
event = gtk.gdk.event_peek()
print 'event:', event
if event is None or event.type not in (gtk.gdk.KEY_PRESS, gtk.gdk.KEY_RELEASE):
return False
return gtk.gdk.keyval_name(event.keyval) == 'Escape'
def runner():
code(_check_esc)
gtk.main_quit()
w = gtk.Window()
w.show()
gobject.idle_add(runner)
gtk.main()
コードを実行すると、Esc キーを押したりマウスを動かしたりしても、出力されるイベントは常に None です。
また、Escape のハンドラーをインストールし、while gtk.events_pending(): gtk.main_iteration()
イディオムを使用してチェッカーにイベントを処理させることも検討しました。これにより、保留中のすべてのイベント (キーボード イベントやマウス イベントを含む) がアンキューされ、ディスパッチされます。その結果、コードの実行中に GUI がレスポンシブ対応になるため、見栄えが悪く、コードの実行に深刻な影響を与える可能性があります。実行中に処理される唯一のイベントは、実行を中断するためのエスケープ キーである必要があります。