2016-01-03 23 views
12

私はPythonでTkinter UIを使ってプログラムを書いています。私はタイトルバーのない小さなウィンドウを持っていたい。このウィンドウにはキーボード入力が必要です。私はこれがEntryウィジェットの形であるのか、KeyPressへのバインディングであるのかはわかりません。 overrideredirect(True)は、通常、タイトルバーが無効になる方法です。残念ながら、(Windowsを除く)、これは多くのイベントが受信されるのを妨げるようです。私はこの問題を説明するために、このコードを書いた:TkinterのoverrideredirectがMacとLinuxで特定のイベントを防ぎます

#!/usr/bin/env python 
from __future__ import print_function 
import Tkinter 

class AppWindow(Tkinter.Tk): 
    def __init__(self, *args, **kwargs): 
     Tkinter.Tk.__init__(self, *args, **kwargs) 
     self.overrideredirect(True) 
     self.geometry("400x25+100+300") 

     titleBar = Tkinter.Frame(self) 
     titleBar.pack(expand = 1, fill = Tkinter.BOTH) 

     closeButton = Tkinter.Label(titleBar, text = "x") 
     closeButton.pack(side = Tkinter.RIGHT) 
     closeButton.bind("<Button-1>", lambda event: self.destroy()) 

     self.bind("<KeyPress>", lambda event: print("<KeyPress %s>" % event.char)) 
     self.bind("<Button-1>", lambda event: print("<Button-1>")) 
     self.bind("<Enter>", lambda event: print("<Enter>")) 
     self.bind("<Leave>", lambda event: print("<Leave>")) 
     self.bind("<FocusIn>", lambda event: print("<FocusIn>")) 
     self.bind("<FocusOut>", lambda event: print("<FocusOut>")) 

if __name__ == "__main__": 
    app = AppWindow() 
    app.mainloop() 

これはそれがそれらを受信したときに一般的なイベントの名前を出力します(タイトルバーなしで)小さなウィンドウを作成します。私はこのスクリプトをWindows 7、Mac OSX(El Capitan)、およびUbuntu 14.04.1で実行しました。私は仮想マシン(VMWare)でUbuntuだけを走らせました。

  • Windowsでは、これは期待どおりに動作しているようです。私のコードがテストするすべてのイベントを受け取ることができます。

  • Ubuntuのでは、Tkinterのウィンドウは<Enter><Leave>、および<Button-1>予想通りのイベントが、<KeyPress><FocusIn>を受け取り、<FocusOut>が受信されることはありません。実際には、ウィンドウがクリックされた後でも、フォーカスを持つ最後のウィンドウはキープレスを受け取り続けます。 OSXで

  • 、Tkinterの窓は、予想通り<Button-1>イベントを受信しますが、<KeyPress><FocusIn>、および<FocusOut>が受信されることはありません。フォーカスを持つ最後のウィンドウは、Ubuntuのようなキーの押下を受け続けることはありません。 <Enter><Leave>イベントはちょっと変な動作をします。 <Enter>イベントは、ウィンドウがクリックされるまで受信されません。その後、<Leave>イベントが発生すると、再度<Enter>イベントを受信するには、ウィンドウを再度クリックする必要があります。

私もちょうど__init__機能の終了前self.focus_force()を試してみました。これにより、プログラムの起動時にウィンドウが<FocusIn>イベントを受信しますが、それ以上のイベントは受信されません。<KeyPress><FocusIn>、または<FocusOut>イベントは受信されません。

最終的に私の質問はこれです:タイトルバーを隠す方法はありますか?OSXとLinuxでキーボード入力を受け続けますか?


この同じ問題を扱う他の質問があります。

受け入れ答えはself.attributes('-fullscreen', True)を使用することです、私は、小さな小さなウィンドウをしませ欲しいと私のために動作しません。これらの3つの質問で全画面アプリケーション。

もう1つの質問があります:Tkinter overrideredirect no longer receiving event bindingsです。これは私の質問に非常に近いと思われますが、詳細は少なく、答えはありません。


アップデート:私は私の問題の根底にあるメカニズムを調べるしようとしてきました。私はTkinterがTcl/Tkのラッパーであることを知っているので、私はTclで自分のコードを書き直そうと思っていました。私は実際のTclを知らないが、私は(多かれ少なかれ)に管理さだと思う私はPythonを翻訳:

#!/usr/bin/env wish 
wm overrideredirect . True 
wm geometry . "400x25+100+300" 
bind . <KeyPress> {puts "<KeyPress %K>"} 
bind . <Button-1> {puts "<Button-1>"} 
bind . <Enter> {puts "<Enter>"} 
bind . <Leave> {puts "<Leave>"} 
bind . <FocusIn> {puts "<FocusIn>"} 
bind . <FocusOut> {puts "<FocusOut>"} 

私はWindowsとMac OSXでの結果のプログラムを試してみました。 Windowsでは、私は<KeyPress>イベントを受け取りましたが、OSXで私はしませんでした。 wm overrideredirect . True行がないと、OSXは<KeyPress>イベントを受信します。したがって、この問題はPythonではなくTcl/Tkのように見えます。

+0

「mainloop」とそれに再度アクセスする方法を無効にしますか?Binding(key listen)はサブ要素で処理します。 'listener'が' frozen'の場合、 'ghost'アプリケーションを取得しました。 – dsgdfg

+0

トリック:[X]ボタンをメインループにしてください( 'deiconify()')! – dsgdfg

答えて

2

この状況ではTkにバグレポートを提出しました。

あなたはあなたの窓から装飾を削除するdevilspieプログラムを使用することができます。 wm title . mynameコマンドを使用して、ウィンドウに特定の名前を付けて、その下のdevilspie構成フラグメントでその名前を使用します。プログラムからoverrideredirectコマンドを削除します。

私はこれを(Tkプログラムとして)テストしましたが、デコレートされていないウィンドウにはキー入力&などのバインディングが引き続き表示されます。 devilspieは、デーモンプロセスとして記述された、アクティブのままされていることを

注。デーモンは起動後に強制終了され、変更されたウィンドウはまだ有効になります。または、実行中のままにしておき、ウィンドウがアクティブになるといつでもdevilspieの設定が適用されます。

(if (is (application_name) "t.tcl") 
    (begin (undecorate))) 
+0

Err ... Linux用です。 Macに相当するプログラムがあるかどうかはわかりません。 –

+0

ありがとう、私にとって完璧に動作します(Archlinux with LXDE)。 –

+0

はoverrideredircctとウィンドウが故意に焦点を取ることが防止されるので、キーイベントを取得することはできません。 http://core.tcl.tk/tk/artifact/7892c68f49012d2d71222ae0e312a1e7dc69a801?txt=1&ln=51-64 その行とコメントがあります古代、削除することが可能かもしれません。 確かに。 – Hugge

関連する問題