【问题标题】:Python tkinter bind hover and keypressPython tkinter 绑定悬停和按键
【发布时间】:2020-08-13 17:47:29
【问题描述】:

我有一个 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, 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 ) 

上述方法都没有提供我正在寻找的结果,当鼠标悬停在画布窗口上并按下 alpha 键时启动回调方法。

感谢您的帮助,谢谢。

【问题讨论】:

  • 我不认为你可以绑定悬停。你可以绑定进入和退出,这样你就可以构建一个函数来检查你在里面的时间以及光标的位置,以确定你是否在悬停。
  • 而不是悬停也许您可以尝试将'&lt;Enter&gt;''&lt;Leave&gt;' 绑定到函数
  • 我的语言说悬停,我的例子使用'',语义。

标签: python tkinter canvas bind


【解决方案1】:

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

基本上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, 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()

【讨论】:

  • 首先,我已将您的代码粘贴到我的 IDE 中并观察到它可以工作。其次,我已将您的代码折叠到我的代码中,但它不起作用。我的直觉是我没有一个普通的香草框架,我实际上在那个框架里装了很多东西。因此,我担心鼠标在技术上并不直接位于“主”框架下方。理想情况下,我不想将每个东西都绑定在“主”框架内。
  • 我在您提供的代码中添加了一些打印语句(我将其折叠到我身边),以测试我关于将东西堆叠在“主”框架的顶部/内部的假设。事实证明,这似乎是一个有效的想法。只有当我处于“主”框架的最边缘时,按键绑定才真正起作用。那么问题来了,我的选择是什么?
  • 你能把你的“主要”框架变成画布吗?如果是这样,请执行此操作并将其转储到 HoverPool。如果您发布代码会有所帮助。我只有您提供的少量信息可供使用。你有可能完全错了。
  • 关于 - 理想情况下,我不想在主框架中绑定所有内容 - 无论您如何执行此操作,您都必须这样做。您不能“悬停”您的应用程序从未被告知“悬停”的东西。但是,您可以使用 mainframe.winfo_children() 将其全部绑定在一个循环中
  • 一些不错的回复,谢谢。我没有发布我的代码,因为问题发生在 GUI 的源代码深处,该 GUI 由类森林组成……隔离代码超出我共享的范围可能会比它的价值更麻烦。
猜你喜欢
  • 2017-09-30
  • 2012-10-30
  • 1970-01-01
  • 2014-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-15
相关资源
最近更新 更多