PfannkuchenXD
PfannkuchenXD

Reputation: 151

Tkinter Focus lost after askstring

I am currently implementing a program that uses many tkinter frames and while subframe is being opened I want the superframe to be locked for the user (otherwise things will not work out). After some research I found the grab_set and grab_release method which worked quite fine.

However once the subframe (instanciated by Toplevel) calls the askstring the grab is "losed" and the user can interact with the superlevel window again. An example would be this (very simplified code):

import tkinter as tk
import tkinter.simpledialog

root = tk.Tk()
def open_sublevel():
    tl = tk.Toplevel(root)
    def ask():
        print(tk.simpledialog.askstring("askstring", "askstring"))
    tk.Button(tl, text="ask", command=ask).pack()
    tl.grab_set()
    root.wait_window(tl)
    tl.grab_release()
    print("release")


tk.Button(root, text="asdf", command=open_sublevel).pack()
tk.mainloop()

Once the user opens the subframe by clicking "asdf" the frame containing "asdf" will be locked for the duration while the subframe is opened. However once the user selects the "ask"-Button in the subframe this "lock" somehow disappears.

Upvotes: 0

Views: 1354

Answers (2)

Cat
Cat

Reputation: 364

setting the parent for simpledialog will make simpledialog take focus

x = simpledialog(parent = window_x, title = z etc.)

this will make sure x takes focus and not withdraw

Upvotes: 0

Mike - SMT
Mike - SMT

Reputation: 15226

According to the notes in the tkinter library:

A grab directs all events to this and descendant widgets in the application.

I am not able so far to find any documentation that would explain why the grab_set() is falling off after you finish submitting your askstring but I would imaging it is because once the widget is gone the grab_set() falls off. Just like if you were to close out the Toplevel window.

In this case tl.grab_release() does not appear to be needed as grab releases once the window closes.

From what I have tested if you reset the grab_set() after the askstring is done then it will still work properly.

You need to simply add tl.grab_set() just below print(tk.simpledialog.askstring("askstring", "askstring")).

Modified code below:

import tkinter as tk
import tkinter.simpledialog

root = tk.Tk()

def open_sublevel():
    tl = tk.Toplevel(root)
    tl.grab_set()

    def ask():
        print(tk.simpledialog.askstring("askstring", "askstring"))
        tl.grab_set()

    tk.Button(tl, text="ask", command=ask).pack()
    print("release")

tk.Button(root, text="asdf", command=open_sublevel).pack()
tk.mainloop()

Upvotes: 1

Related Questions