0

I've got a series of 16 Tk Entry widgets that I'd like to bind <Key> events to so anything with a visible effect fills in (like a, 7, and *) while any keys without immediately visible effects have their keysym representation put in place instead (Return, Tabx, Shift_L, etc...)

If I bind <Key> to each of these Entry widgets, anything with a visible event.char double prints. Anything with an invisible one does not. If I bind <Key> to the root, this doesn't happen.

Considering my actual program has a few buttons and a canvas, is it a bad idea to bind <Key> to root?
If so, how can I bind it to each widget individually and avoid double printing anything without an empty event.char?

#!/usr/bin/env python
#sample.py
import tkinter as tk

def set_key(event):
    print(f"Key: '{event.char}', '{event.keysym}'")
    focus = root.focus_get()
    focus.delete(0, tk.END)
    if (event.char.split() != []):
        focus.insert(0, event.char)
    else:
        focus.insert(0, event.keysym)

root = tk.Tk()
root.option_add("*Font", "24")

keys = ["1", "2", "3", "4", "q", "w", "e", "r", "a", "s", "d", "f", "z", "x", "c", "v"]
keyboard_entries = []
for idx in range(16):
    keyboard_entries.append(tk.Entry(root, width=7))
    keyboard_entries[idx].grid(row=(idx//4), column=(idx%4))
    keyboard_entries[idx].insert(0, keys[idx])
    #keyboard_entries[idx].bind("<Key>", set_key) #Problematic

root.bind("<Key>", set_key) #Not problematic
root.mainloop()

Results when binding to root
Results when binding to each Entry

ig-
  • 105
  • 7
  • Does this answer your question? [how-to-bind-self-events-in-tkinter-text-widget-after-it-will-binded-by-text-widg](https://stackoverflow.com/a/3513906/7414759) – stovfl Apr 24 '20 at 07:07
  • using the same set_key function as above, I can add a new bindkey to go after .entry and Entry but before . and all. It works if I bind to that new bindkey, but I don't know how much I like it, and I do wonder if there's a way that feels less like I'm rearranging tk innards without really understanding what I'm doing – ig- Apr 24 '20 at 07:22

1 Answers1

0

Considering my actual program has a few buttons and a canvas, is it a bad idea to bind to root?

Yes, it is a bad idea. Binding to root means that every widget will be affected.

If so, how can I bind it to each widget individually and avoid double printing anything without an empty event.char

Well, you could always bind to each widget individually. It looks like you already tried that, but it's not clear why you think it's not working.

keyboard_entries[idx].bind("<Key>", set_key)

As for how to not get double characters, the problem is that the default bindings to the keys are happening after your bound function is called. The simplest solution is to prevent the original binding from firing is by returning "break" from your function.

Also, you don't need to get the focus in your function because part of the event object is a reference to the widget that received the event.

def set_key(event):
    event.widget.delete(0, "end")
    if (event.char.split() != []):
        event.widget.insert(0, event.char)
    else:
        event.widget.insert(0, event.keysym)
    return "break"

For a longer explanation of events and bindings see this answer: http://stackoverflow.com/a/11542200/7432

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • Thank you! `return "break"` to prevent the default binding was what I was looking for! And you're right, I should have said binding to each widget individually wasn't working as I wanted it to, not that it wasn't working. The binding did work for the most part. And thank you for the event.widget part! – ig- Apr 24 '20 at 17:32