Python Forum
Is there a way to call and focus any popup window outside of the main window app?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Is there a way to call and focus any popup window outside of the main window app?
#6
(Oct-01-2023, 02:56 PM)Valjean Wrote:
(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


Thanks. I t worked. And yes.. I need the popup window to be place a little below the current caret position...this is my acutal code:


def create_popup(tk_queue, key_listener_instance):
    print("Entered create_popup")  # Debugging
    while True:
        queue_data = tk_queue.get()
        msg, data = queue_data[:2]  # Only take the first two values

        current_window = getActiveWindow()
        current_win_title = current_window.title if current_window else "Unknown Window"
        
        if msg == "create_popup":
            print("About to stop listener and create popup")  # Debugging
            key_listener_instance.stop_listener()

            windows = gw.getWindowsWithTitle(current_win_title)
            if windows:
                main_win = windows[0]
                pyautogui.click(main_win.left + 10, main_win.top + 10)
            else:
                print(f"No window with title '{current_win_title}' found.")

            popup = ctk.CTk()  # Use ctk instead of tk
            popup.title("Select Expansion")

            for i, option in enumerate(key_listener_instance.expansions_list):
                raw_button_text = option['expansion'] if 'expansion' in option else "Undefined"
                button_text = truncate_text(raw_button_text, 60)
                button = ctk.CTkButton(
                    popup,
                    text=button_text,
                    command=partial(key_listener_instance.make_selection, i, popup),
                    font=("Work Sans", 12),
                    anchor="w"
                )
                button.pack(fill=ctk.X, padx=10, pady=5)

            # Update idle tasks to get updated dimensions
            popup.update_idletasks()

            # Get the content width and height
            content_width = 400
            content_height = popup.winfo_height()

            # Set the geometry of the popup to fit the content
            popup.geometry(f"{content_width}x{content_height}")
          
         
            def on_closing():
                try:
                    print("Trying to restart the listener...")  # Debugging
                    key_listener_instance.start_listener()  # Start the listener
                except Exception as e:
                    print(f"Failed to restart listener. Exception: {e}")
                finally:
                    popup.destroy()

            popup.protocol("WM_DELETE_WINDOW", on_closing)
            print("Setting WM_DELETE_WINDOW protocol")  # Debugging

            popup.attributes("-topmost", True)
            popup.focus_force()

            print("Entering Tkinter mainloop")  # Debugging
            popup.mainloop()
Reply


Messages In This Thread
RE: Is there a way to call and focus any popup window outside of the main window app? - by Valjean - Oct-01-2023, 04:39 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  Hide CMD call window tester_V 8 694 Apr-16-2024, 08:26 PM
Last Post: deanhystad
  Open files in an existing window instead of new Kostov 2 555 Apr-13-2024, 07:22 AM
Last Post: Kostov
  How to Minimize ADB window OomKoos 0 495 Dec-29-2023, 12:41 PM
Last Post: OomKoos
  add entries and labels to the window tkinter jacksfrustration 3 862 Oct-10-2023, 06:41 PM
Last Post: buran
  Can't stop keyboard listener to grab chars typed inside CTk window Valjean 9 1,674 Sep-25-2023, 08:07 PM
Last Post: deanhystad
  read active document name - other than from the window title ineuw 0 635 Sep-11-2023, 09:06 AM
Last Post: ineuw
  how to open a popup window in tkinter with entry,label and button lunacy90 1 1,137 Sep-01-2023, 12:07 AM
Last Post: lunacy90
Bug tkinter.TclError: bad window path name "!button" V1ber 2 1,026 Aug-14-2023, 02:46 PM
Last Post: V1ber
  Howto do motion event on solely window and not the widgets on it? janeik 3 1,026 Jul-11-2023, 12:10 AM
Last Post: deanhystad
  What is all the info in the info window in Idle? Pedroski55 3 868 Jul-08-2023, 11:26 AM
Last Post: DeaD_EyE

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020