Tkinter键盘绑定

时间:2012-08-02 16:07:52

标签: python tkinter keyboard-shortcuts

我正在使用Tkinter和canvas小部件开发一个界面,到目前为止已经找到了我从其他问题和发布的答案中得到的问题的答案,但我对此感到困惑。

我在创建GUI元素的类中有几个键盘绑定,并且在程序启动时它们都可以正常工作。绑定看起来像这样:

self.canvas.get_tk_widget().bind("<Control-o>",self.flash_open)

并且在类的__init__函数内。截至昨天,我初始化了这门课程 启动程序,然后等待用户从菜单中选择打开,然后打开(除其他外)一个tkmessagebox

self.specfilename =askopenfilename(filetypes=[("spec", "")],initialdir= self.pathname)

使用此文件名,我可以从特定文件类型中检索所需的变量名称(对问题无关紧要)。今天我修改了__init__函数,在程序启动时调用open函数。由于在打开此文件之前无法执行任何其他操作,因此首先打开它是有意义的。选择文件并关闭Tkmessagebox后,根窗口处于活动状态,但键盘绑定都不起作用。我的功能仍然可以使用分配给它们的菜单/按钮,而不是绑定。我已经尝试将快捷方式绑定到root,结果相同,我现在认为这可能是我调用它们的顺序的问题

def __init__(self):
    ...
    self.openfile() #calls the tkmessagebox
    self.root.mainloop() #starts gui

我之前遇到过这个问题,其中一个toplevel()实例被关闭/销毁并禁用了父窗口的绑定。没有任何错误信息可言,绑定只是不做任何事情。我还应该提一下,我已经尝试使用

再次关注根窗口
self.openfile()
self.root.mainloop()
self.root.focus_set()

我之前使用wm_withdraw()和wm_deiconify()函数来隐藏子窗口,然后在程序完成后关闭它。但是,在这种情况下,此修复更难以应用。如果有人能够解释问题的原因,我会很感激。

编辑:

我已经编写了一个可运行的代码段来准确显示我的问题。

import os
from tkFileDialog import askopenfilename
from Tkinter import *


class Start:
    def __init__(self):

        self.root = Tk()
        self.root.title('Binding Troubles')
        menubar = Menu(self.root)
        #add items and their commands to the menubar
        filemenu = Menu(menubar, tearoff=0)
        filemenu.add_command(label="Do work", command=self.do_work)
        filemenu.add_command(label="Open File",command=self.openfile)
        menubar.add_cascade(label="File", menu=filemenu)
        #bind control-o to perform the do work function
        self.root.bind("<Control-o>",self.flash_do_work)
        self.root.bind("<Control-O>",self.flash_do_work)
        #add the menubar to the GUI
        self.root.config(menu=menubar) 
        #initially open a tkdialog to open a file
        self.openfile()#comment out this line to make the bind work 
        self.root.focus()#also tried self.root.focus_set()
        self.root.mainloop()
    def flash_do_work(self,event):
        #indirect tie to the do_work() function, I'm don't know a 
        #proper way to make functions handle calls from both events and non-events
        self.do_work()
    def openfile(self):
        #gets current path
        self.pathname = os.getcwd()
        #Requests filename using a tkdialog
        self.filename =askopenfilename(initialdir= self.pathname)
        print self.filename
    def do_work(self):
        #placeholder for actual function; shows whether the bind is working or not
        print "work"

Start()

如果从__init__中删除self.openfile()并且仅在菜单中使用

,则绑定将起作用

另一个编辑:我再次更新了示例,给出了一个菜单选项来运行openfile()函数。我注意到如果在__init__中调用openfile(),则绑定将不起作用。但是如果再次调用openfile函数,这次从菜单手动,bind将再次开始工作。不完全确定从这里采取什么。此外,我对帖子这么长时间表示道歉。

1 个答案:

答案 0 :(得分:5)

更改

self.openfile()

self.root.after(1, self.openfile)

这会将对askopenfilename的调用移动到主事件循环中。将它放在主事件循环之外会以某种方式破坏你的事件绑定。