byt*_*zed 13 python linux tk-toolkit tkinter tcl
我正在用Python编写一个带有Tkinter UI的程序.我想要一个没有标题栏的小窗口.此窗口必须接收键盘输入.我不挑剔这是以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()
Run Code Online (Sandbox Code Playgroud)
这会创建一个小窗口(没有标题栏),在收到它们时会打印公共事件的名称.我在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>事件.
我也在函数self.focus_force()结束前尝试过__init__.这会导致窗口接收<FocusIn>事件在程序启动时,但没有进一步的<KeyPress>,<FocusIn>或<FocusOut>事件从未收到.
最终,我的问题是:有没有办法隐藏标题栏但是继续在OSX和Linux中接收键盘输入?
我知道处理同样问题的其他一些问题.在这三个问题中:
接受的答案是使用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>"}
Run Code Online (Sandbox Code Playgroud)
我在Windows和Mac OSX中尝试了生成的程序.在Windows中我收到了<KeyPress>事件,但在OSX中我没有收到.没有这wm overrideredirect . True条线,OSX确实收到了这些<KeyPress>事件.因此看起来这个问题不是用Python,而是用Tcl/Tk.
我已针对这种情况向 Tk 提交了错误报告。
您可以使用该devilspie程序删除窗户上的装饰。使用该wm title . myname命令为您的窗口指定一个特定名称,并在devilspie下面的配置片段中使用该名称。overrideredirect从程序中删除该命令。
我已经测试过这个(作为 Tk 程序),未修饰的窗口仍然会接收按键等。绑定。
请注意,它devilspie被编写为守护进程并保持活动状态。守护进程在启动后可以被终止,并且它所做的窗口更改仍然有效。或者它可以保持运行,并且任何时候激活窗口时,devilspie都会应用配置。
(if (is (application_name) "t.tcl")
(begin (undecorate)))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1099 次 |
| 最近记录: |