Я пишу программу на Python с пользовательским интерфейсом Tkinter. Я хочу иметь небольшое окно без заголовка. Это окно должно принимать ввод с клавиатуры. Я не придирчива, является ли это формой виджета Entry или просто привязывается к KeyPress. overrideredirect(True)
, как правило, отключена строка заголовка. К сожалению, (за исключением Windows), это, по-видимому, предотвращает получение многих событий. Я написал этот код, чтобы проиллюстрировать проблему:
#!/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()
Это создает небольшое окно (без заголовка), которое печатает имя общих событий, когда оно их получает. Я запустил этот script в Windows 7, Mac OSX (El Capitan) и Ubuntu 14.04.1. Я запускал только Ubuntu на виртуальной машине (VMWare).
-
В Windows это похоже на работу. Все события, которые мои тесты кода могут быть получены.
-
В Ubuntu окно Tkinter получает события
<Enter>
,<Leave>
и<Button-1>
, как ожидалось, но<KeyPress>
,<FocusIn>
и<FocusOut>
никогда не принимаются. Фактически даже после того, как окно было нажато, последнее окно с фокусом продолжает получать нажатия клавиш. -
В OSX окно Tkinter получает события
<Button-1>
, как ожидалось, но<KeyPress>
,<FocusIn>
и<FocusOut>
никогда не принимаются. Последнее окно с фокусом не продолжает получать нажатия клавиш, например, в Ubuntu. События<Enter>
и<Leave>
ведут себя немного странно. Событие<Enter>
не принимается до щелчка по окну. Затем, как только произойдет событие<Leave>
, окно нужно снова щелкнуть, чтобы получить другое событие<Enter>
.
Я также пробовал self.focus_force()
непосредственно перед завершением функции __init__
. Это приводит к тому, что окно получает событие <FocusIn>
, когда программа запускается, но не более чем <KeyPress>
, <FocusIn>
или <FocusOut>
события не принимаются.
В конечном счете, мой вопрос заключается в следующем: есть ли способ скрыть строку заголовка, но продолжать получать ввод с клавиатуры в OSX и Linux?
Мне известны некоторые другие вопросы, касающиеся этой же проблемы. В этих трех вопросах:
- python tkinter overrideredirect; не может получать нажатия клавиш (Linux)
- root.overrideredirect и < Any-KeyPress > связывание
- Как связать Tkinter destroy() с ключом в Debian?
Принятый ответ - использовать self.attributes('-fullscreen', True)
, который не будет работать для меня, поскольку я хочу маленькое маленькое окно, а не полноэкранное приложение.
Есть еще один вопрос: Tkinter overrideredirect больше не получает привязки событий. Это кажется очень близким к моему вопросу, но предоставлено меньше деталей и не имеет ответа.
Обновление:. Я пытаюсь исследовать основной механизм моей проблемы. Я знаю, что 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.