当前位置: 首页 > 知识库问答 >
问题:

Tkinter's overrideredirect防止Mac和Linux中的某些事件

郭通
2023-03-14

我正在用Python编写一个带有Tkinter UI的程序。我想有一个没有标题栏的小窗口。此窗口必须接收键盘输入。我并不挑剔这是一个条目小部件的形式,还是仅仅绑定到KeyPress。 通常是禁用标题栏的方式。不幸的是,(除了在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()

这将创建一个小窗口(没有标题栏),当它接收到公共事件时,该窗口将打印这些事件的名称。我已经在Windows7,Mac OSX(El Capitan)和Ubuntu14.04.1上运行了这个脚本。我只在虚拟机(VMWare)中运行Ubuntu。

>

在Ubuntu中,Tkinter窗口按预期接收 事件,但从不接收 。事实上,即使在窗口已经被点击之后,最后一个有焦点的窗口继续接收按键。

在OSX中,Tkinter窗口按预期接收 /code>事件,但从不接收 /code>, /code>和 /code>。最后一个有焦点的窗口不会像在Ubuntu中那样继续接收按键。 /code>和 /code>事件的行为有点奇怪。单击窗口后才会收到 /code>事件。然后,一旦发生 /code>事件,则需要再次单击窗口以接收另一个 /code>事件。

我还在 函数结束之前尝试了 。这会导致窗口在程序启动时接收 /Code>事件,但不会再接收进一步的 /Code>, /Code>或 /Code>事件。

最终,我的问题是:在OSX和Linux中,有没有什么方法可以隐藏标题栏,但继续接收键盘输入?

我知道还有其他一些问题与这个问题有关。在这三个问题中:

    ;Binding/LI>

公认的答案是使用 ,这对我不起作用,因为我需要一个很小的窗口,而不是一个全屏应用程序。

还有一个问题: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中,我收到 /code>事件,但在OSX中没有。没有 行,OSX确实接收 /code>事件。因此,看起来这个问题不是Python的问题,而是tcl/Tk的问题。

共有1个答案

彭宏深
2023-03-14

我已经针对这种情况向Tk提交了一份错误报告。

您可以使用 程序从窗口中移除装饰。请使用 命令为您的窗口指定一个特定的名称,并在下面的 配置片段中使用该名称。从程序中删除 命令。

我已经对此进行了测试(作为一个Tk程序),未修饰的窗口仍然会收到按键&ampetc。绑定。

请注意, 是作为守护进程编写的,并且保持活动状态。守护进程可以在启动后终止,而它所做的窗口更改仍然有效。或者它可以保持运行状态,并且在您的窗口被激活时,将应用 配置。

(if (is (application_name) "t.tcl")
   (begin (undecorate)))
 类似资料:
  • 问题内容: 我们有一个Android / Blackberry项目,其中有一个共同的部分。显然,该部分被编写为可同时针对Android和Blackberry目标进行编译,因此无法使用某些较新的Java功能(例如Integer.valueOf)。我想跳过一些专门针对该部分的规则。有没有办法做到这一点? 问题答案: 如果将通用零件分离到自己的项目,则可以在Sonar中添加新的质量配置文件(在其中停用了

  • 有没有办法防止事件链中的一些听众为事件开火,但允许链上的其他人开火? 比如我有这个结构 假设我已经将单击事件监听器连接到body、div#1和div#2。是否有可能在div#2事件监听器上阻止事件进入div#1或介于两者之间的任何其他监听器,并允许事件在body元素上触发? 我这样说是因为我使用谷歌地图和emberjs构建了一系列可以在地图上显示的交互式信息框。问题是ember将事件侦听器附加到b

  • 我使用Spring Boot框架构建了一个REST接口。然后,我使用Swagger版本2.9.2来生成文档。从下面的照片可以看到,Swagger自动检测了很多模型。 所以,我的问题是:我怎么告诉Swagger该曝光哪些模特? 下面是我的控制器的Swagger配置和代码片段。 控制器:

  • 问题内容: 我们在www.saddleback.com/live上有一个网页,Chrome和Firefox CORS AJAX调用在某些Mac机器上被中止。在装有OSX 10.9(最新更新),Chrome和Firefox(最新更新)的Mac上,对http://api.saddleback.com/WorshipService?version=2&null&_=1386201207191的AJAX调

  • 问题内容: 我有几个使用共享资源(数据库)的作业,有时这会在(碰巧)同时触发作业的(罕见)事件中导致构建失败。 例如,给定作业A到E,是否有任何方法可以指定A和C 绝不能同时运行 ? 除上述资源外,构建彼此独立(例如,不存在上游/下游关系)。 “强力”方式将执行者的数量限制为一个,但是如果大多数作业可以很好地同时执行并且在构建服务器上不缺少计算资源,那么显然这不是理想的选择。 问题答案: 当前有两

  • 问题内容: 我想创建一个触发器,以防止在出生日期(列之一)将来的时候插入。我有这个: 如何取消if语句中的插入? 问题答案: 基于这一点,我不确定是否可以这样做。 MySQL当前的触发器实现中不支持自愿引发异常并中止生成触发器的语句。 我发现的解决方法是编写一个BEFORE触发器,以将表中的not-NULL列之一设置为NULL,从而违反了其NOT NULL约束。这导致产生触发器的语句被中止。