Python tkinter绑定悬停和按键

问题描述

我有一个tkinter画布窗口,试图使用方法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,'<Enter> <p>',self.parameter_window_operator ) 

    self.element_block = self.canvas.create_window( (0,'<Enter p>','<Enter-p>','<Enter+p>',self.parameter_window_operator ) 

以上方法均无法提供我想要的结果,当鼠标悬停在画布窗口上方并按下Alpha键时,会启动回调方法

感谢您的帮助,谢谢。

解决方法

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

基本上HoverPool使画布不断检查鼠标下的内容。如果某个东西在“ hoverpool”中被触发,则focus_set()被触发,这使得它的键绑定起作用。

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,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,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()