0

I have a canvas with a rectangle and I want to detect if someone pressed the rectangle together with a key (ie "shift"). In Matplotlib the mouse event can do that with the key property. Wondering if tkinter has somehting similar? I tried this solution

from tkinter import *

root = Tk()

def key(event):
    print("pressed", repr(event.char))

def callback(event):
    print("clicked at", event.x, event.y)

canvas= Canvas(root, width=100, height=100)
canvas.bind("<Key>", key)
canvas.bind("<Button-1>", callback)
canvas.pack()

root.mainloop()

but it doesn't detect key events, only the mouseclick events work.

Tom
  • 2,545
  • 5
  • 31
  • 71
  • 1
    You might want to take a look at this: [check if modifier key is pressed in tkinter](https://stackoverflow.com/questions/19861689/check-if-modifier-key-is-pressed-in-tkinter) – Bryan Oakley Jul 14 '22 at 21:50

1 Answers1

2

Instead of detecting whether the shift key is pressed or not, you can bind to the <Shift-Button-1> event so that the callback is only called if the user shift-clicks on the object.

Here is an example that will display the color of an item when you shift-click on it.

import tkinter as tk

def handle_click(event):
    color = event.widget.itemcget("current", "fill")
    label.configure(text=f"item color: {color}")

root = tk.Tk()

canvas = tk.Canvas(root, background="bisque")
label = tk.Label(root)

label.pack(side="bottom", fill="x")
canvas.pack(fill="both", expand=True)

canvas.create_rectangle(10, 10, 110, 110, fill="red", tags=("rectangle",))
canvas.create_rectangle(150, 10, 200, 110, fill="green", tags=("rectangle",))

canvas.tag_bind("rectangle", "<Shift-Button-1>", handle_click)

root.mainloop()

screenshot of window with red and green canvas items

If you want to handle multiple combinations of modifier keys (alt, shift, control, meta, etc) you can bind to <1> and examine the state attribute of the event object. However, there are platform dependencies that make that problematic. I personally find making individual bindings easier and more straight-forward.

For more on how to use the event.state attribute, see check if modifier key is pressed in tkinter

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • that works, but when I try to print out the key (so I can distinguish between shift and alt for example like so: `print(event.char)` in only returns `??`, why is that? – Tom Jul 14 '22 at 21:23
  • 2
    @Tom: you can set up separate bindings for ``. – Bryan Oakley Jul 14 '22 at 21:40
  • but then i have 5 different bindings for each of the keys I want to address. Is there not an easier way to do so? What is `.char`, `.keycode`, etc. for if they all return `??`. – Tom Jul 14 '22 at 21:43
  • 2
    @Tom: those are for bindings to keys. – Bryan Oakley Jul 14 '22 at 21:46
  • it looks like the `state` property on the event seems to change when different buttons are pressed in combination with the mouse click. Any idea where I could find what the state property is? – Tom Jul 18 '22 at 23:31
  • 1
    _"it looks like the state property on the event seems to change when different buttons are pressed in combination with the mouse click."_ yes, that is correct. As for what values it has, I think it's platform-dependent. This is why I recommend binding on specific states. – Bryan Oakley Jul 19 '22 at 00:29