0

I have an tkinter application with several windows, which often are placed over each other in a window stack, so that only a topmost window is visible. In this topmost window I can press a button which causes one of the not visible windows to run popen. The process which is started is also a tkinter application and is finished automatically some milliseconds later. After this, without any other action by the user, the topmost window is moved behind the second window of my window stack and the second window gets the topmost window.

Why is that? How can I keep the topmost window at top?

With my example code you have to create several windows by the "new window" button. Then move all windows over each other in the order the window number gives. Put the window with number 1 as topmost window. Then press "run in last window" and a new different window will show. Press there the "exit" Button and then the window with number 2 will jump into foreground.

import tkinter as tk
import subprocess
all_windows = []
count = 1
class ButtonWindow(tk.Toplevel):
    def __init__(self):
        global count
        super().__init__()
        self.title(count)
        count += 1
        button_new = tk.Button(self, command=ButtonWindow, text="new window", width=50)
        button_run = tk.Button(self, command=self.run_in_last_window, text="run in last window", width=50)
        button_new.grid()
        button_run.grid()
        all_windows.append(self)
    def run_in_last_window(self):
        last_window = all_windows[-1]
        last_window.run_popen()
    def run_popen(self):
        print("run popen in", self)
        command_array = ["Py", "-c", "import tkinter as tk; root=tk.Tk();b=tk.Button(root,text='exit',command=exit);b.grid();root.mainloop()"]
        process = subprocess.Popen(command_array, text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        for line in process.stdout:
            print("line =", line)
        process.wait()
root = tk.Tk()
root.withdraw()
ButtonWindow()
root.mainloop()
2
  • 1
    is your second window the one that calls popen? Commented Oct 23 at 17:02
  • No, always the last one runs popen Commented Oct 23 at 17:49

1 Answer 1

0

process = subprocess.Popen(command_array, ...)

When you run that line, it opens a new python.exe process that creates another top-level window. This new process temporarily gets primary focus.

To fix this you should manually reassign the topmost property after the new window is created to regain priority.

Sign up to request clarification or add additional context in comments.

1 Comment

You are right, I already had tried this by inserting "self.lift()" after "last_window.run_popen()", but with no success. Today I found the solution: Inserting "self.after_idle(self.lift)" at the same place helps. It seems that closing a tkinter toplevel window brings a "next" tkinter toplevel into foreground, but not the one where the run button was pressed. How can I control this mechanism? And still it is not clear why "after_idle" is needed, as "process.wait()" is used.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.