Oct-01-2023, 02:56 PM
(Sep-30-2023, 01:59 PM)deanhystad Wrote: I looked back at some of your other posts. I think you switched over to using the keyboard module to catch keystrokes. I modified my earlier code to use the same module and to fit better with the code you have posted. While doing this I noticed there is no reason for the popup to capture keystrokes. The KeyListener knows when the popup is visible, and it knows what keys are pressed. It can forward key presses to the popup when visible. That fixes your focus problem.
import tkinter as tk import string import keyboard class Popup(tk.Tk): """Popup window for displaying option buttons.""" It worked!!! Thanks so much!!! **dance** def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.withdraw() self.command = None self.shurtcuts = {} self.title("Popup") self.protocol("WM_DELETE_WINDOW", lambda: self.select(None)) def configure(self, options=None, command=None, **kwargs): """Adds options and command to configure.""" super().configure(**kwargs) self.command = command or self.command if options: for widget in self.winfo_children(): widget.destroy() self.shortcuts = dict(zip(string.ascii_lowercase, options)) for key, op in self.shortcuts.items(): button = tk.Button( self, text=f"{key}: {op}", command=lambda x=op: self.select(x) ) button.pack(expand=True, fill=tk.X) def open(self): """Draw window.""" self.deiconify() def shortcut(self, key): """Check if key is shortcut.""" if key in self.shortcuts: self.select(self.shortcuts[key]) def select(self, option): """Button press callback.""" self.withdraw() self.command(option) class KeyListener: """Listens to key presses. Executes command if key event is mapped.""" keychars = {"space": " ", "tab": "\t", "enter": "\n"} def __init__(self): self.word = [] self.popup = Popup() self.commands = { "Do this": lambda: print("Doing this"), "Do that": lambda: print("Doing that"), "Clear": self.word.clear, "Quit": self.popup.destroy } self.popup.configure( command=self.popup_callback, options=list(self.commands) ) keyboard.on_press(self.on_press) self.popup.mainloop() def popup_callback(self, option): """Popup window callback.""" self.commands[option]() def on_press(self, key): """Called when keyboard key is pressed.""" key = self.keychars.get(key.name, key.name) if self.popup.state() == "normal": # Redirect to popup. self.popup.shortcut(key) elif key == "esc": # Open command popup. self.popup.open() else: # Do some input processing thing. if key in string.printable: self.word.append(key) print("".join(self.word)) KeyListener()Not having to run the keyboard listener in another threads simplifies things. You don't have to create a thread, and you don't have to stop the thread. Other changes are asking the popup window if it is visible instead of using a variable to keep track and using a dictionary to hold the popup commands