'Root window jump to front when opening file dialog in child window tkinter

I'm using tkinter in python to make 2 windows in 2 diffrent classes, their root window open a new window and to make the child window to be on top I'm using lift(), but when I'm pressing button that open file dialog window, the root window jump to front again, I've tried also to make the child window on top always using attributes('-topmost', True) but then it's appearing above the dialog window as well.
How do I make the root window always stays lower and not come back up?



Solution 1:[1]

You can guarantee a child window will have the focus with filedialog, like this.

image = fido.askopenfilename( parent = child, title = "Pick an image" )

Transient applied to child window will make child sit in front of parent but will not stop parent from being the focus after loading data.

I've set program so you can test this, just set conditional statement to True and by removing parent = child from filedialog.

Code has been expanded to fully test tkinter behaviour

Tkinter Experiments:

Test Tk and Toplevel windows for focus control and image display when using tk.filedialog.askopenfilename

Conclusion:

Unless explicitly set after filedialog closes, the final focus will always go to the widget defined in filedialog (default = parent).

Setting child to transient will not affect the final focus.

Also, if child is tk.Tk() then tk.PhotoImage requires both file = image and master = parent|child, otherwise a _tkinter.TclError: image "pyimage1" doesn't exist error is thrown.

If child is tk.Toplevel() then tk.PhotoImage only requires file = image to successfully display photo!

import os
import tkinter as tk
from tkinter import filedialog as fido

parent = tk.Tk()
parent.title("Parent")

# Give tkinter time to compute parent size and position
parent.update()

# Extract window dimensions from parent
x, y, w = parent.winfo_x(), parent.winfo_y(), parent.winfo_width()

if False:

    # Create child as `Toplevel`
    child = tk.Toplevel(parent)
    child.title("Child")

    # Test usefulness of transient in controlling focus
    if True:
        child.transient(parent)

else:

    # Create child as `Tk
    child = tk.Tk()
    child.title("Child")

#  Place both windows side by side
child.geometry( f"+{x+w+10}+{y}" )

if False:

    # TEST 1: Focus will ulitmately go to parent
    child.focus_set()
    image = fido.askopenfilename( title = "Pick an image" )

else:

    # TEST 2: Focus will ulitmately go to child
    parent.focus_set()
    image = fido.askopenfilename( parent = child, title = "Pick an image" )

# Demonstrate that placing data (image) in child will not alter the focus
if image:
    if True:

        # Try loading image method #1: Will show image
        photo = tk.PhotoImage(master = child, file = image)

    else:

        # Try loading image method #2: Will throw error
        photo = tk.PhotoImage(file = image)

    # Display photo in `label`
    label = tk.Label(
        child, image = photo, foreground = "white", font = "Consolas 20 normal",
        compound = tk.CENTER, text = os.path.split( image )[1])
    label.pack(fill=tk.BOTH, expand=True)

parent.mainloop()

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1