tkinter.simpledialog.Dialog让发起的tkinter.Button保持按下状态

3

我正在使用Windows 7上的Python 3.3。 我有一个基于tkinter的应用程序,其中一个Button会启动一个tkinter.simpledialog.Dialog。 像这样(这是一个完整可运行的示例):

import tkinter
import tkinter.simpledialog

class Mainframe(tkinter.Frame):
    def __init__(self, parent):
        super(Mainframe, self).__init__(parent)
        self.parent = parent
        self.button = tkinter.Button(self, text="Open Dialog")
        open_dialog_op = lambda ev: self.open_dialog(ev)
        self.button.bind("<Button-1>", open_dialog_op)
        self.button.bind("<Return>", open_dialog_op)
        self.button.pack(side=tkinter.LEFT)

    def open_dialog(self, event):
        dialog = tkinter.simpledialog.Dialog(self.parent, "My Dialog")
        self.button.config(relief=tkinter.RAISED)  # does not help!

root = tkinter.Tk()
Mainframe(root).pack()
root.mainloop()

行为:
  • 如果您将焦点放在“打开对话框”按钮上并键入“RETURN”,一切都很好
  • 如果您单击鼠标“按钮”,则对话框出现得很好,但是
  • 当对话框关闭时,“打开对话框”按钮以其沉没状态(如果我没有错的话,则为tkinter.SUNKEN)显示。
  • (有趣的是,在对话框打开时,按钮通常显示。 只有在对话框关闭后才会开始压抑的外观。)
  • 我尝试通过简单调用button.config(relief=tkinter.RAISED)来修复问题, 但在这种情况下似乎根本没有任何作用。

(实际上,我的完整应用程序在单击按钮后就开始显示按钮被按下的状态, 而不仅仅是在对话框再次关闭后。 我认为这更加合理: simpledialog本地事件循环抓取所有事件,因为simpledialog是模态的; 这可能包括ButtonRelease-1鼠标事件在按钮上?)

问题:

  1. 为什么会发生这种情况?
  2. 为什么我的完整应用程序中的行为可能不同?
  3. 如何避免或修复两者?
2个回答

3
这是因为您部分地覆盖了默认绑定所执行的操作。
如果您想要在按钮“激活”时执行一个函数,正确的方法是向按钮添加一个command选项。我使用“激活”而不是“按下”的原因是,正如您的代码所显示的那样,在tk中有多种激活按钮的方式:按钮按下、回车、加速键按下等等。
您编写的代码并没有取代相当大的默认绑定集合。iCodez的答案确实正确修复了最明显的缺陷,但保留默认绑定并使用command=将适用于您未经测试的情况(例如仅使用键盘操作)。

0

对于第三个问题,我有一个简单的解决方案。实际上,在您的帖子中,您自己已经给出了答案。请更改此行:

self.button.bind("<Button-1>", open_dialog_op)

转换为:

self.button.bind("<ButtonRelease-1>", open_dialog_op)

现在,open_dialog_op 绑定到鼠标点击的释放上。这意味着 simpledialog 只有在按钮弹起时才会打开(这是它应该具有的行为)。

然而,我也想提出建议。为什么不使用 tkinter.messagebox.askokcancel 呢?它与 Windows 系统提示相同。请参见下面:

tkinter.simpledialog.Dialog 对话框:

enter image description here

tkinter.messagebox.askokcancel 对话框:

enter image description here


为什么会发生这种情况的第一个问题的答案是,按钮的抬起是在释放按钮时发生的,而由于代码覆盖了默认行为,导致释放无法被处理,直到对话框被关闭。正确的解决方案不是在<ButtonRelease>上添加绑定,而是使用内置的command属性,它可以正确地处理所有绑定和行为。 - Bryan Oakley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接