我无法绑定箭头键事件

Posted

技术标签:

【中文标题】我无法绑定箭头键事件【英文标题】:I can't bind the arrow key events 【发布时间】:2021-12-28 16:29:01 【问题描述】:

我目前有一个下一个切片和上一个切片按钮,可以单击它们以在图像中移动。我还希望键盘左右箭头允许用户浏览上一个和下一个切片。所以应该有两种方法来浏览图像。我无法在prev_imagenext_image 内获得键盘点击工作。

import tkinter as tk

class App(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)  # python3 style
    
        self.master.title("Slideshow")

        top_frame = tk.Frame(self)
        top_frame.pack()
    
        image_frame = tk.Frame(self)
        image_frame.pack()

        previous_button = tk.Button(top_frame, text="Previous Slice", command=self.prev_image)
        previous_button.pack(side="left")

        next_button = tk.Button(top_frame, text="  Next Slice  ", command=self.next_image)
        next_button.pack(side="left")

        self.canvas = tk.Canvas(image_frame, bg='red')
        self.canvas.pack()
    
        self.canvas.bind('<Left>', self.prev_image)
        self.canvas.bind('<Right>', self.next_image)
        self.canvas.focus_set()

        self.master.bind('<Left>', self.prev_image)
        self.master.bind('<Right>', self.next_image)
    
    def prev_image(self, event=None):
        print('prev_image')
        if event:
            print('even:', event)

    def next_image(self, event=None):
        print('next_image')
        if event:
            print('even:', event)

root = tk.Tk()
app = App(root)
app.pack()
root.mainloop()

 

图片:

【问题讨论】:

您只需绑定一次。也许使用self.master.bind() 而不是self.canvas.bind()。或者它可能需要在canvas 上设置focus()。或者先创建root = tk.Tk(),然后使用root.bind() 当我删除第二个 self.canvas.bind 并将第一个更改为 self.master.bind() 时,我收到错误消息“next_image() 需要 1 个位置参数但 2被给予” 可能先在函数中使用print(),看看是否执行。也许它运行这些功能,但你可能有不同的问题 - 比如bug in PhotoImage 如果您创建最小的工作代码,我们可以简单地复制和测试它会更简单。当前代码缺少Canvasload_imageimage_set_rowscurrent_image_index 请edit 提出您的问题并提供runnable minimal reproducible example 的代码,我相信有人可以提供帮助。 【参考方案1】:

您必须在canvas 上设置focus 才能获取canvas 中的密钥

        self.canvas.bind('<Left>', self.prev_image)
        self.canvas.bind('<Right>', self.next_image)
        self.canvas.focus_set()

或者您可以将键绑定到主窗口

        self.master.bind('<Left>', self.prev_image)
        self.master.bind('<Right>', self.next_image)

第二个版本可能会更好,因为canvas 可能会丢失focus - 即。当您使用键 tab 从小部件跳转到小部件时。


其他问题。

command= 需要不获取参数的函数,但 bind() 需要获取一个参数的函数 - 因为它发送有关事件的信息(即按下的键、鼠标位置等)

要在command=bind() 中使用相同的函数,您需要具有默认值的参数 - 即。 even=None

    def prev_image(self, event=None):
        # ... code ...

    def next_image(self, event=None):
        # ... code ...

最小的工作示例:

import tkinter as tk

class App(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)  # python3 style
        
        self.master.title("Slideshow")

        top_frame = tk.Frame(self)
        top_frame.pack()
        
        image_frame = tk.Frame(self)
        image_frame.pack()
    
        previous_button = tk.Button(top_frame, text="Previous Slice", command=self.prev_image)
        previous_button.pack(side="left")

        next_button = tk.Button(top_frame, text="  Next Slice  ", command=self.next_image)
        next_button.pack(side="left")

        self.canvas = tk.Canvas(image_frame, bg='red')
        self.canvas.pack()
        
        #self.canvas.bind('<Left>', self.prev_image)
        #self.canvas.bind('<Right>', self.next_image)
        #self.canvas.focus_set()

        self.master.bind('<Left>', self.prev_image)
        self.master.bind('<Right>', self.next_image)
        
    def prev_image(self, event=None):
        print('prev_image')
        self.canvas['bg'] = 'blue'
        if event:
            print('even:', event)

    def next_image(self, event=None):
        print('next_image')
        self.canvas['bg'] = 'green'
        if event:
            print('even:', event)


if __name__ == "__main__":
    app = App()
    app.pack()
    app.mainloop()
    
    #root = tk.Tk()
    #app = App(root)
    #app.pack()
    #root.mainloop()

【讨论】:

谢谢!!如果我按下下一个箭头键,您对添加 self.canvas.focus_set() 的建议的最小工作示例适用于下一个图像,但对于上一个图像,它给了我相同的“prev_image() 需要 1 个位置参数,但给出了 2 个" 错误 我的例子没有问题。您必须在 next_imageprevious_image 两个函数中使用 event=None 搞定了,谢谢!!

以上是关于我无法绑定箭头键事件的主要内容,如果未能解决你的问题,请参考以下文章

取消绑定 wxPython 中的默认按钮行为

是否有可能看到我在C#WPF中按下数据网格上的向下箭头如何将事件绑定到该?

Tkinter中的多个键事件绑定 - “Control + E”“Command(apple)+ E”等

为啥 Python 会在 Pygame 中为“事件”变量抛出未绑定的本地错误? [关闭]

vue - 结合腾讯地图时绑定监听要使用箭头函数不然无法绑定

使用键绑定将操作绑定到 3 个或更多键的组合