Tkinter's Overrideredirect verhindert bestimmte Ereignisse in Mac und Linux

Ich schreibe ein Programm in Python mit einer Tkinter-Benutzeroberfläche. Ich möchte ein kleines Fenster ohne Titelleiste haben. Dieses Fenster muss eine Tastatureingabe erhalten. Ich bin nicht wählerisch, ob dies in Form eines Eintrags-Widgets oder nur als Bindung an KeyPress vorliegt.overrideredirect(True) ist in der Regel, wie die Titelleiste deaktiviert ist. Leider scheint dies (mit Ausnahme von Windows) zu verhindern, dass viele Ereignisse empfangen werden. Ich habe diesen Code geschrieben, um das Problem zu veranschaulichen:

#!/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()

Dadurch wird ein kleines Fenster (ohne Titelleiste) erstellt, in dem der Name der allgemeinen Ereignisse gedruckt wird, wenn sie empfangen werden. Ich habe dieses Skript unter Windows 7, Mac OS X (El Capitan) und Ubuntu 14.04.1 ausgeführt. Ich habe nur Ubuntu in einer virtuellen Maschine (VMWare) ausgeführt.

In Windows scheint dies wie erwartet zu funktionieren. Alle Ereignisse, auf die mein Code testet, können empfangen werden.

In Ubuntu erhält das Tkinter-Fenster<Enter>, <Leave>, und<Button-1> Ereignisse wie erwartet, aber<KeyPress>, <FocusIn>, und<FocusOut> werden nie empfangen. Selbst nachdem das Fenster angeklickt wurde, erhält das letzte Fenster mit dem Fokus weiterhin die Tastendrücke.

Unter OSX erhält das Tkinter-Fenster<Button-1> Ereignisse wie erwartet, aber<KeyPress>, <FocusIn>, und<FocusOut> werden nie empfangen. Das letzte Fenster mit Fokus empfängt keine Tastendrücke mehr wie in Ubuntu. Das<Enter> und<Leave> events verhalten sich etwas merkwürdig. Das<Enter>as @ -Ereignis wird erst empfangen, wenn auf das Fenster geklickt wird. Dann, sobald das<Leave>enn ein @ -Ereignis auftritt, muss das Fenster erneut angeklickt werden, um ein weiteres @ zu erhalte<Enter> Veranstaltung

Ich habe auch versuchtself.focus_force() kurz vor dem Ende des__init__ Funktion. Dadurch erhält das Fenster ein<FocusIn> Ereignis, wenn das Programm startet, aber nicht weiter<KeyPress>, <FocusIn>, oder<FocusOut> Ereignisse werden nie empfangen.

Letzt meine Frage lautet: Gibt es eine Möglichkeit, die Titelleiste auszublenden, aber weiterhin Tastatureingaben in OSX und Linux zu erhalten?

Ich bin mir einiger anderer Fragen bewusst, die sich mit demselben Problem befassen. In diesen drei Fragen:

python tkinter overrideredirect; kann keine Tastatureingaben empfangen (Linux) root.overrideredirect und <Any-KeyPress> BindungWie binde ich Tkinter destroy () an einen Schlüssel in Debian?

Die akzeptierte Antwort lautetself.attributes('-fullscreen', True), was bei mir nicht funktioniert, da ich ein kleines Fenster und keine Vollbildanwendung haben möchte.

Es gibt noch eine andere Frage:Tkinter overrideredirect empfängt keine Ereignisbindungen mehr. Dies scheint meiner Frage sehr nahe zu sein, ist aber weniger detailliert und kann nicht beantwortet werden.

Aktualisieren Ich habe versucht, den zugrunde liegenden Mechanismus meines Problems zu untersuchen. Ich weiß, dass Tkinter ein Wrapper um Tcl / Tk ist, also dachte ich, ich würde versuchen, meinen Code in Tcl umzuschreiben. Ich kenne Tcl nicht wirklich, aber ich glaube, ich habe es geschafft, mein Python (mehr oder weniger) zu übersetzen:

#!/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>"}

Ich habe das resultierende Programm unter Windows und Mac OS X ausprobiert. In Windows erhielt ich<KeyPress> Events, aber in OSX habe ich nicht. Ohne daswm overrideredirect . True line, OSX erhält das<KeyPress> Veranstaltungen. Daher sieht es so aus, als ob dieses Problem nicht bei Python, sondern bei Tcl / Tk liegt.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage