Tkinter check which Entry last had focus

2024/9/22 19:46:40

I am working on a program that has a virtual keyboard I created using Tkinter. The pages that have the keyboard enabled have entry widgets where the users need to input data. I am using pyautogui as part of the virtual keyboard to simulate the keyboard presses, but my issue is the widget that is focused when a user presses on any of the buttons on the keyboard. Since each keyboard button is a ttk.Button when they press the keys, the button has the focus, and not the Entry widget they had selected they were trying to put data in.

As such right now I have the method which runs the keypresses, calling a specific widget to become the focus before it does the key press. Here's the code I have right now:

import tkinter as tk
from tkinter import ttk
import pyautoguidef drawKeyboard(parent):keyboardFrame = tk.Frame(parent)keyboardFrame.pack()keys = [[ ("Alpha Keys"),[ ('q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'),(' ', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'),('capslock', 'z', 'x', 'c', 'v', 'b', 'n', 'm'),('delete', 'backspace', 'home', 'end')]],[ ("Numeric Keys"),[ ('7', '8', '9'),('4', '5', '6'),('1', '2', '3'),(' ', '0', ' ')]]]for key_section in keys:sect_vals = key_section[1]sect_frame = tk.Frame(keyboardFrame)sect_frame.pack(side = 'left', expand = 'yes', fill = 'both', padx = 10, pady = 10, ipadx = 10, ipady = 10)for key_group in sect_vals:group_frame = tk.Frame(sect_frame)group_frame.pack(side = 'top', expand = 'yes', fill = 'both')for key in key_group:key = key.capitalize()if len(key) <= 1:key_button = ttk.Button(group_frame, text = key, width = 4)else:key_button = ttk.Button(group_frame, text = key.center(5, ' '))if ' ' in key:key_button['state'] = 'disable'key_button['command'] = lambda q=key.lower(): key_command(q)key_button.pack(side = 'left', fill = 'both', expand = 'yes')def key_command(event):entry1.focus()pyautogui.press(event)returnroot = tk.Tk()
entry1 = tk.Entry(root)
entry1.pack()
entry2 = tk.Entry(root)
entry2.pack()
drawKeyboard(root)
root.mainloop()

Obviously manually calling entry1.focus() does me no good if I want to input data into entry2. And calling entry2.focus() does no good if I want to put data into entry1. So is there a way for me to every time one of my buttons is pressed check to see which Entry Widget last had focus?

I need to check for specifically entry widgets as the final screen will also have some radio buttons and such. Thanks for your time

EDIT: I made a quick change to the code, exchanging the Shift key for the Capslock key. I realized that the way my code worked Shift would never actually work since you couldn't exactly hold it down and press another button.

Answer

You can set the attribute takefocus to False to prevent the buttons from taking focus. This has the unfortunate side effect of not being able to traverse the buttons using the keyboard (which might be ok, since you're in a no-keyboard situation)

...key_button = ttk.Button(..., takefocus=False)
...
def key_command(event):entry = root.focus_get()entry.insert("end", event)pyautogui.press(event)return

Another solution is to add a binding on the <FocusIn> event where you can save the widget in a global variable.

def key_command(event):focused_entry.insert("end", event)pyautogui.press(event)returndef remember_focus(event):global focused_entryfocused_entry = event.widgetentry1.bind("<FocusIn>", remember_focus)
entry2.bind("<FocusIn>", remember_focus)

If you have many entry widgets, you can do a class binding on the Entry class instead:

root.bind_class("Entry", "<FocusIn>", remember_focus)
https://en.xdnf.cn/q/71914.html

Related Q&A

Python Popen grep

Id like Popen to execute:grep -i --line-buffered "grave" data/*.txtWhen run from the shell, this gives me the wanted result. If I start, in the very same directory where I test grep, a python…

Url structure and form posts with Flask

In Flask you write the route above the method declaration like so: @app.route(/search/<location>/) def search():return render_template(search.html)However in HTML the form will post to the url in…

How can I simulate a key press in a Python subprocess?

The scenario is, I have a Python script which part of it is to execute an external program using the code below:subprocess.run(["someExternalProgram", "some options"], shell=True)An…

Difference between pd.merge() and dataframe.merge()

Im wondering what the difference is when you merge by pd.merge versus dataframe.merge(), examples below:pd.merge(dataframe1, dataframe2)anddataframe1.merge(dataframe2)

ctypes in python crashes with memset

I am trying to erase password string from memory like it is suggested in here.I wrote that little snippet:import ctypes, sysdef zerome(string):location = id(string) + 20size = sys.getsizeof(string)…

Python __del__ does not work as destructor? [duplicate]

This question already has answers here:What is the __del__ method and how do I call it?(5 answers)Closed 4 years ago.After checking numerous times, I did find inconsistent info about the topic.In some…

How to set default button in PyGTK?

I have very simple window where I have 2 buttons - one for cancel, one for apply. How to set the button for apply as default one? (When I press enter, "apply" button is pressed)However, I wa…

Can Python recognize changes to a file that it is running interactively?

I was doing some troubleshooting and I was curious if it is possible to run a Python script interactively, change a function defined in the script, save the file, then have the interactive shell recogn…

How to use FTP with Pythons requests

Is it possible to use the requests module to interact with a FTP site? requests is very convenient for getting HTTP pages, but I seem to get a Schema error when I attempt to use FTP sites. Is there …

How to find a best fit distribution function for a list of data?

I am aware of many probabilistic functions builted-in Python, with the random module. Id like to know if, given a list of floats, it would be possible to find the distribution equation that best fits t…