Search code examples
pythontk-toolkit

tk.TopLevel is making two windows appear, but why?


The code below generates my main program (frmMain), which sometimes opens forms. But each time I open a form, the code below makes TWO forms open, the proper form, and one extra one, which is blank. The standard top-right close button only works on the proper form, and, the extra one is invulerable. But why does it appear, and why is it invulnerable?

frmMain=tk.Tk()

def createForm():
    lFrm = tk.Toplevel()    #Create a new form
    initForm(lFrm)          #tk.inits the form and sets the mass onFocus event bubble
    return lFrm
    
def initForm(pFrm):
    tk.Toplevel.__init__(pFrm) #instead of super
    #super().__init__(master=pFrm)
    setWindowFocusEvent(pFrm) #when any win gets focus, all windows come to fore in order (as per std MDI app behaviour)

An example of where I might call this is below, but it causes TWO windows to appear:

def listBands():
    global frmMain
    frmMain.lListBandsFrm = createForm()

There are some threads on SO about two windows appearing at once, but in those examples I can see what the cause was. But in my case, I really can't. I'm not calling any spurious tk.Tk(), and I'm only calling tk.Toplevel() once for each form. Stepping through the code reveals that both windows appear simultaneously when createForm finishes.

I've tried omitting the init() call, but that of course breaks everything, e.g., I can't call .bind until after init.

The answer is... not to fiddle with init, and to properly use inheritance and subclassing. Here it is:

class FrmMDI(tk.Toplevel):  #New form, with my own setup as required
    def __init__(self):     #Autocalled when obj is instantiated
        super().__init__()  #Calls the init() of the parent
        setWindowFocusEvent(self) #My own prep, to improve MDI in Windows

def createForm():      #This was giving me double-windows
    lFrm = FrmMDI()    #Create a new form using subclass of .Toplevel
    return lFrm

Solution

  • The answer is... not to fiddle with init, use the built-in and simpler super() instead. It was getting confusing which forms were calling my own custom init(), and when I needed to call it. And, rather than write your own Init() that you call from certain forms, it's better to make your own subclass. It then gets easy to understand, and init() works smoothly. Here's those things in code:

    class FrmMDI(tk.Toplevel):  #New form based on Toplevel, with my own extra setup step
        def __init__(self):     #Autocalled when obj is instantiated
            super().__init__()  #Calls the init() of the parent
            setWindowFocusEvent(self) #My own prep, to improve MDI in Windows
    
    def createForm():      #This was giving me double-windows
        lFrm = FrmMDI()    #Create a new form using subclass of .Toplevel
        return lFrm