当用户在模态窗口外单击时如何响铃? [英] How to sound a bell when the user clicks outside a modal window?

查看:30
本文介绍了当用户在模态窗口外单击时如何响铃?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

情况很简单.我有一个带有帮助 - 关于菜单的主窗口.单击此菜单项时,将打开一个模式窗口(假设它是一个关于窗口).使用 self.grab_set() 我禁用了主窗口(尽管单击主标题栏时模式窗口会闪烁).到目前为止,一切都很好.

The situation is simple. I have a main window with a Help - About menu. When this menu item is clicked, a modal window is opened (let's say it's an About-window). With self.grab_set() I disabled the main-window (although the modal window does flicker when you click the main title bar). So far, so good.

问题是:当用户在主窗口的模态窗口外点击时,我真的很喜欢响铃.

Here is the question: I really like to sound a bell when the user clicks outside the modal window on the main window.

这是我能找到的关于grab_set()的东西,真的没有那么多:

This is what I could find about grab_set(), really not that much:

  • [effbot] ...一个名为grab_set的方法,它确保没有鼠标或键盘事件被发送到错误的窗口.
  • [effbot] 将此应用程序的所有事件路由到此小部件.
  • [kite.com] 抓取将所有事件定向到应用程序中的此小部件和后代小部件.
  • [谷歌图书]grab_set() 确保应用程序的所有事件都发送到 w,直到对grab_release 进行相应的调用([Me:] 或直到窗口被销毁?)

我不太确定如何理解这一点:这是否意味着您可以在模态窗口中处理主窗口上的事件(例如敲响我的钟声)?所以我尝试了这样的事情:

I'm not quite sure how to understand this: does it mean you can handle an event on the main window within the modal window (like sounding my bell)? So I tried things like:

self.bind('', self.bell) Tkinter 回调中的异常:_tkinter.TclError:错误的窗口路径名parent.bind('', self.bell) 什么都没发生

self.bind('<Button-1>', self.bell) Exception in Tkinter callback: _tkinter.TclError: bad window path name parent.bind('<Button-1>', self.bell) Nothing happens

那么,像在许多其他应用程序中一样,在主窗口的模态窗口之外单击时如何发出铃声?

So, how to sound a bell like when clicked outside the modal window on the main window, like in so many other applications?

衍生问题:

  • 使用后是否还可以从主窗口捕获事件模式窗口的grab_set?
  • 有没有办法防止闪烁?

我真的很想了解这个神秘的grab_set()方法.

I really like to understand this mysterious grab_set() method.

剥离代码:

import tkinter as tk

class About(tk.Toplevel):
    def __init__(self, parent):
        tk.Toplevel.__init__(self, parent)
        self.geometry('200x150')

        #--- OK button
        btn_ok = tk.Button(self, text='OK', command=self.destroy)  # destroy with OK
        btn_ok.pack(side=tk.TOP)
        btn_ok.focus()                                             # destroy with spacebar

        #--- Make window modal
        self.grab_set()                 
        # self.wait_window()              # is this necessary in this case?
        # self.bind('<Button-1>', self.bell) ??? The question

class MenuBar(tk.Menu):
    def __init__(self, parent):
        tk.Menu.__init__(self)
        helpmenu = tk.Menu(self, tearoff=0)
        helpmenu.add_command(label='About', command=lambda: About(parent))
        self.add_cascade(label='Help', menu=helpmenu)

class MainApp():
    def __init__(self, parent):
        parent.configure(background='#000000')
        parent.geometry('800x600')
        menubar = MenuBar(parent)
        parent.configure(menu=menubar)

if __name__ == '__main__':
    root = tk.Tk()
    MainApp(root)
    root.mainloop()

推荐答案

当您设置抓取时,所有按钮点击都将转到带有抓取的窗口.您可以像捕获任何其他事件一样捕获它们.在单击按钮的情况下,您可以通过将函数绑定到 <1> 来实现.

When you set a grab, all button clicks will go to the window with the grab. You capture them the way you capture any other event. In the case of a button click you do that by binding a function to <1>.

重要的是要知道根窗口或 Toplevel 窗口上的绑定将应用于该窗口中的所有小部件.例如,即使您单击确定"按钮,在您的代码中绑定到 self 也会触发.因此,回调应该只在与事件关联的小部件与顶层相同时才起作用.

It's important to know that a binding on a root window or a Toplevel window will apply to all widgets in that window. For example, binding to self in your code will fire even when you click on the "Ok" button. Therefore, the callback should probably only do work when the widget associated with the event is the same as the toplevel.

示例:

class About(tk.Toplevel):
    def __init__(self, parent):
        ...
        self.bind("<1>", self.capture_click)
        ...
    def capture_click(self, event):
        if event.widget == self:
            <your logic here>

如果想知道用户是否点击了窗口外,可以通过事件对象的坐标与窗口进行比较,看点击是在窗口内还是外.

In the case of wanting to know if the user clicked outside the window, you can use the coordinates of the event object to compare against the window to see if the click is inside or outside.

    def on_click(self, event):
        if event.widget == self:
            if (event.x < 0 or event.x > self.winfo_width() or
                event.y < 0 or event.y > self.winfo_height()):
                self.bell()

这篇关于当用户在模态窗口外单击时如何响铃?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆