Python tkinter 绑定悬停和按键

Python tkinter bind hover and keypress

我有一个 tkinter canvas window 并尝试使用方法 tag_bind 绑定事件组合,鼠标悬停并按下特定字母。

我试过的是:

    self.element_block = self.canvas.create_window( (0, 0), window=self.block_main, anchor="nw", width=self.block_width, height=self.block_height )
    self.canvas.tag_bind( self.element_block, '<Enter><p>', self.parameter_window_operator )

    self.element_block = self.canvas.create_window( (0, 0), window=self.block_main, anchor="nw", width=self.block_width, height=self.block_height )
    self.canvas.tag_bind( self.element_block, '<Enter> <p>', self.parameter_window_operator ) 

    self.element_block = self.canvas.create_window( (0, 0), window=self.block_main, anchor="nw", width=self.block_width, height=self.block_height )
    self.canvas.tag_bind( self.element_block, '<Enter p>', self.parameter_window_operator ) 

    self.element_block = self.canvas.create_window( (0, 0), window=self.block_main, anchor="nw", width=self.block_width, height=self.block_height )
    self.canvas.tag_bind( self.element_block, '<Enter-p>', self.parameter_window_operator ) 

    self.element_block = self.canvas.create_window( (0, 0), window=self.block_main, anchor="nw", width=self.block_width, height=self.block_height )
    self.canvas.tag_bind( self.element_block, '<Enter+p>', self.parameter_window_operator ) 

None 以上方法提供了我正在寻找的结果,当鼠标悬停在 canvas window 上并按下 alpha 键时启动回调方法。

感谢您的帮助,谢谢。

甚至不用担心 tag_bind。您可以移动得太快而无法注册事件。我知道原因,这是我为您提供的第一个解决方案,即使您正常使用鼠标它也能正常工作,但如果您不使用它,它就会损坏。请尝试以下方法。

基本上 HoverPool canvas 不断检查鼠标下方的内容。如果它是“悬浮池”中的某物,它就会被 focus_set() 触发,这使得它 key-bindings 可以工作。

import tkinter as tk


class HoverPool:
    def __init__(self, canvas):
        self.hoverpool = dict()
        self.canvas = canvas
        self.canvas.bind("<Motion>", self.check)
        
    def addWidget(self, target, tag, pos, **kwargs):
        self.hoverpool[tag] = target
        win   = self.canvas.create_window(pos, window=target, **kwargs)
        self.canvas.itemconfig(win, tag=(tag))

    def check(self, event):
        if len(self.canvas.gettags('current')):
            for k, v in self.hoverpool.items():
                if k in self.canvas.gettags('current'):
                    v.focus_set()
                    return
                    
        self.canvas.master.focus_set()


class App(tk.Tk):
    WIDTH, HEIGHT, TITLE = 800, 600, 'Application'

    def __init__(self):
        tk.Tk.__init__(self)
        self.canvas = tk.Canvas(self, background='red')
        self.canvas.pack(fill='both', expand=True, side='left')
        
        #init hoverpool
        hoverpool = HoverPool(self.canvas)
                 
        self.frame1 = tk.Frame(self, background='green', height=50, width=50)
        self.frame1.bind('<Key-p>', self.onFrame1Action)
        self.frame1.bind('<Key-b>', self.onFrame1Action)
        
        #add frame1 to the hover pool
        hoverpool.addWidget(self.frame1, 'frame1', (50,50), anchor='nw')
        
        self.frame2 = tk.Frame(self, background='green', height=50, width=50)
        self.frame2.bind('<Key-p>', self.onFrame2Action)
        self.frame2.bind('<Key-b>', self.onFrame2Action)
        
        #add frame2 to the hover pool
        hoverpool.addWidget(self.frame2, 'frame2', (105,50), anchor='nw')
        
    def onFrame1Action(self, event):
        if event.char == 'p':
            self.frame1['background'] = 'purple' 
        if event.char == 'b':
            self.frame1['background'] = 'black'
           
    def onFrame2Action(self, event):
        if event.char == 'p':
            self.frame2['background'] = 'pink' 
        if event.char == 'b':
            self.frame2['background'] = 'blue' 


if __name__ == '__main__':
    app = App()
    app.title(App.TITLE)
    app.geometry(f'{App.WIDTH}x{App.HEIGHT}')
    app.resizable(width=False, height=False)
    app.mainloop()