下面的代码是一个函数的一部分,它生成一个带有调用者选择的文本和按钮的简单对话框。
问题在于处理'' a'' d'和&#c; c的关键输入。代码可以正确操作鼠标单击和标签,后跟空格或输入键。该代码是用Python 3.4编写的,目前正在测试是否符合Windows 7的要求。
我的理解是Tk为最终用户的鼠标点击处理重新聚焦。在用户通过Tab键更改焦点后使用空格和输入键。对于所有这些交互,密钥通过代码绑定到每个按钮:
for action in ('<1>', '<space>', '<Return>'):
b.bind(action, handler)
对于&#39;强调&#39;键输入我相信我的代码需要在调用处理程序之前处理重新聚焦。这是重新聚焦例程的目的。打印声明(&#34;重新聚焦到......&#34;)打印时,button.winfo_name()的值正确,只要&#39;&#39; a&#39;&#39;,& #39; s&#39;或&#39; c&#39;被压了。这就是为什么我认为button.focus_set()
失败了。
如果有效,这将使处理程序只需通过查看event.widget.winfo_name()
来检查按下了哪个按钮。实际上,重新聚焦失败意味着使用event.widget.winfo_name()
如果我通过标签手动移动焦点,则焦点会显示event.widget.winfo_name()
返回的名称,而不管其中的哪个&#39;&#39; a&#39;&#39; d& #39;或者&#39; c&#39;被压了。
在阅读Stack Overflow上的其他帖子后,我尝试在button.focus_force()
之后添加button.focus_set()
。这对问题没有影响。
我尝试通过将处理程序的签名更改为def button_handler(event, *args)
然后将refocus
的最后一行更改为handler(event,button.winfo_name())来传递按钮名称,但是{{1调用时为空。
*args
答案 0 :(得分:2)
您最初关于需要将焦点设置在按钮上的假设是不正确的。在Tk中处理此问题的常用方法是在对话框顶层窗体上绑定加速键事件,并调用事件绑定的按钮调用方法。
在Tcl / Tk中:
toplevel .dlg
pack [button .dlg.b -text "Save" -underline 0 -command {puts "Save pressed"}]
bind .dlg <Alt-s> {.dlg.b invoke}
所以将关键事件绑定到任何顶层是你的按钮的父级。如果那是一个对话框,那么它的父对象应该是应用程序toplevel小部件。
等效的python是:
from tkinter import *
main = Tk()
dialog = Toplevel(main)
button = Button(dialog, text="Send", underline="0", command=lambda: print("hello"))
button.pack()
dialog.bind('<Alt-s>', lambda event: button.invoke())
main.mainloop()
键绑定将一个事件对象追加到回调函数中,我们可以使用lambda将该函数包装为按钮的调用方法。
答案 1 :(得分:0)
focus_set()
当然是完美的。我期望重新聚焦会重写事件对象是错误的。以下代码(经过广泛修订以纳入Brian Oakley的建议)产生了预期的结果。:
def _make_buttons(dialog, buttons, buttonbox, default, handler):
def bcommand_wrapper(button):
def bcommand():
name = button.winfo_name()
dialog.destroy()
handler(name)
return bcommand
for button_text, underline, button_name in buttons:
b = ttk.Button(buttonbox, text=button_text, underline=underline,
name=button_name)
b.configure(command=bcommand_wrapper(b))
b.pack(padx=2, side='left')
action = button_text[underline:underline + 1].lower()
try:
dialog.bind(action, lambda event, b=b: b.invoke())
except tk.TclError:
raise ValueError(
"Invalid underline of '{}' in position {}. Character '{}'.".
format(button_text, underline, action))
b.bind('<Return>', lambda event, b=b: b.invoke())
if not default or default == button_name:
default = button_name
b.focus_set()
我放弃了将Tk事件返回给调用者的原始想法。这是一个对话框,因此调用者不需要比单击按钮的名称更多的内容。
请注意,我没有使用&#39; Alt&#39;来捕获加速键。修改。 &#39; Alt&#39;至少在MS Windows上,键与加速键一起使用时是一个功能键:它会在菜单上显示下划线。这里的下划线是静态的,所以使用&#39; Alt&#39;关键是不合适的。
答案 2 :(得分:-1)
我建议您使用root.bind(&#39; c&#39;,)让快捷键执行您想要的操作?
确保只在窗口弹出时绑定它们,并在完成后解除绑定。