1

I have a gui in python3 that I want to call another python script using subprocess (or something better?). I have the main gui full screen, which is what I want. The problem is, when I launch the subprocess, it initially becomes the topmost window on LXDE, so far so good. You can click on the main gui in the background which brings the main gui to topmost. This is what is expected from the window manager, but this covers the subprocess that I currently have blocking the main gui. I need to prevent the main gui from accepting focus while the subprocess is running or keeping the subprocess as topmost window.

maingui.py

#!/usr/bin/env python3
import tkinter as tk
import subprocess

def on_escape(event=None):
    print("escaped")
    root.destroy()

def do_something():
    child = subprocess.run(["python3", "childgui.py"], shell=False)

######################################################################
busy=False
root = tk.Tk()
root.title("My GUI")
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
#don't run this as the subprocess blocks #root.attributes("-fullscreen", True) # run fullscreen
root.focus_set()
root.bind("<Escape>", on_escape)
#doesn't work#root.protocol("WM_TAKE_FOCUS", on_focus) 
canvas = tk.Canvas(root)
canvas.grid(row=0)
cbutton = tk.Button(root, text = "Run Child", width=50, height=50, bg = "green", compound = "top", command = do_something)
lab = tk.Label(canvas, text = 'Output Here')
lab.grid(row=0, column=1)
cbutton.grid(row=1, column=0)
# --- start ---
root.mainloop()

childgui.py

from tkinter import *

class app(Frame):
    def __init__(self, master):
        Frame.__init__(self, master=None)
        self.master.title("Child Process")
        self.master.geometry("500x200")
        Button(self.master, text="Grandchild", command=self.dialog).pack()
        self.data = StringVar()
        self.data.set("Here is the data")
        Label(self.master, textvariable=self.data).pack()

    def dialog(self):
        d = MyDialog(self.master, self.data, "Grandchild", "Enter Data")
        self.master.wait_window(d.top)

class MyDialog:
    def __init__(self, parent, data, title, labeltext = '' ):
        self.data = data
        self.rt = parent
        self.top = Toplevel(parent)
        self.top.transient(parent)
        self.top.grab_set()
        self.top.geometry("300x100")
        if len(title) > 0: self.top.title(title)
        if len(labeltext) == 0: labeltext = 'Data'
        Label(self.top, text=labeltext).pack()
        self.top.bind("<Return>", self.ok)
        self.e = Entry(self.top, text=data.get())
        self.e.bind("<Return>", self.ok)
        self.e.bind("<Escape>", self.cancel)
        self.e.pack(padx=15)
        self.e.focus_set()
        b = Button(self.top, text="OK", command=self.ok)
        b.pack(pady=5)

    def ok(self, event=None):
        print ("The data:", self.e.get())
        self.data.set(self.e.get())
        self.top.destroy()

    def cancel(self, event=None):
        self.top.destroy()

def main():
    root = Tk()
    a = app(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Edit: I should have mentioned the child gui is an app that is not mine. I only created this one for the example code to show the issue. While self.top.attributes may work, the actual child app is pretty large and I don't want to change it if I can avoid it. I don't have problems getting the focus, which is actually the problem. The main gui gets the focus back causing the subprocess to go behind. When the main gui is set to fullscreen (delete this to see #don't run this as the subprocess blocks #) the main gui is now stuck waiting for the child to close which you can't get to with the mouse

skidoo
  • 119
  • 2

0 Answers0