Переадресация Tkinter предотвращает определенные события в Mac и Linux

Я пишу программу на 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() 

Это создает небольшое окно (без заголовка), которое печатает имя общих событий, когда оно их получает. Я запустил этот скрипт в 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> при запуске программы, но больше не <FocusOut> событий <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 wm overrideredirect . True строка, OSX получает события <KeyPress> . Поэтому похоже, что эта проблема не с Python, а с Tcl / Tk.

One Solution collect form web for “Переадресация Tkinter предотвращает определенные события в Mac и Linux”

Я представил отчет об ошибке в Tk для этой ситуации.

Вы можете использовать программу devilspie для удаления украшений из вашего окна. Используйте wm title . myname wm title . myname чтобы дать вашему окну определенное имя и использовать это имя в devilspie конфигурации devilspie ниже. Удалите команду overrideredirect из вашей программы.

Я протестировал это (как программу Tk), и в незадекларированном окне по-прежнему будет нажата клавиша и т. Д. привязок.

Обратите внимание, что devilspie записывается как процесс демона и остается активным. Демон может быть убит после его запуска, и внесенное им изменение окна все равно будет действовать. Или он может быть запущен, и в любое время, когда ваше окно будет активировано, будет применена конфигурация devilspie .

 (if (is (application_name) "t.tcl") (begin (undecorate))) 
  • Дерево python tkinter получает выбранные значения элемента
  • Как изменить цвет текстового курсора в Tkinter?
  • Python TKinter получает тег clicked в текстовом виджете
  • Значение tkinter get () python из поля ввода
  • Получение состояния Tkinter Check Box
  • методы программирования tkinter и GUI
  • Python tkinter: обновить графический интерфейс между вызовами подпроцесса
  • Как изменить фон кадра в Tkinter?
  • Python - лучший язык программирования в мире.