【问题标题】:How can I switch the focus between toplevels of a tkinter program?How can I switch the focus between toplevels of a tkinter program?
【发布时间】:2022-12-02 01:11:01
【问题描述】:

I am using key-accelerators for menu entries in a multi window program. But when an accelerator-key is pressed, then always the same window reacts to the key.

As you can see in my example code, I tried to change the focus by binding the event "FocusIn" to the toplevel and to the canvas. At the event I tried focus_force() and focus_set(). But the accelerator key event is always recognized in the last opened window. This is my example code:

import tkinter as tk
from   tkinter import ttk

class win:
    number = 0
    def __init__(self):
        win.number += 1
        self.number = win.number

        self.top = tk.Toplevel()
        self.top.protocol("WM_DELETE_WINDOW", lambda: self.close_root())
        self.top.bind_all("<Control-o>", lambda event : self.menu())

        self.file_menu_button = ttk.Menubutton(self.top, text="File menu of top" + str(self.number))
        self.file_menu_button.grid()
        self.file_menu = tk.Menu(self.file_menu_button)
        self.file_menu.add_command(label="Open", accelerator="Ctrl+o", command=self.menu)
        self.file_menu_button.configure(menu=self.file_menu)

        self.canvas = tk.Canvas(self.top, width=400, height=200)
        self.canvas.grid()

        self.top.bind("<FocusIn>", lambda event: self.top.focus_force())
        #self.top.bind("<FocusIn>", lambda event: self.top.focus_set())
        self.canvas.bind("<FocusIn>", lambda event: self.top.focus_force())
        #self.canvas.bind("<FocusIn>", lambda event: self.top.focus_set())

    def close_root(self) : root.quit()
    def menu(self): print("menu" + str(self.number) + " clicked")

root = tk.Tk()
root.withdraw()
win1 = win()
win2 = win()
root.mainloop()

【问题讨论】:

    标签: python tkinter focus


    【解决方案1】:

    I found the problem is caused by this line from my example code above:

    self.top.bind_all("<Control-o>", lambda event : self.menu())
    

    This line always gives the last new created toplevel the binding. All previous created toplevel windows loose the binding in this moment. So this line must be removed. Instead the binding must be created new at any time when a toplevel window gets the focus. This can be done in this way:

    self.top.bind("<FocusIn>",
                   lambda event:
                   self.top.bind_all("<Control-o>", lambda event : self.menu()))
    

    【讨论】:

      猜你喜欢
      • 2021-07-18
      • 2022-11-20
      • 2022-12-02
      • 2022-12-27
      • 2022-12-02
      • 2022-12-26
      • 2022-12-02
      • 2022-12-02
      • 2022-12-01
      相关资源
      最近更新 更多