Domagoj Domagoj - 4 months ago 10
Python Question

Making top window inaccessible in wx.python

How can I make top frame inaccessible while child frame is open?

import wx

class MyFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title, size=(400, 320), style=(wx.MINIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN))

# Setting up menu
filemenu = wx.Menu()
set_m = filemenu.Append(wx.ID_PREFERENCES, 'Settings', 'Settings')
# filemenu.Append(US)
filemenu.AppendSeparator()
exit_m = filemenu.Append(wx.ID_EXIT)

# Creating the menubar
menubar = wx.MenuBar()
menubar.Append(filemenu, 'Menu')
self.SetMenuBar(menubar)

self.Bind(wx.EVT_MENU, self.OnSettings, set_m)

def OnSettings(self, e):
SetFrame().Show()

class SetFrame(wx.Frame):
title = 'Settings'
def __init__(self):
wx.Frame.__init__(self, wx.GetApp().TopWindow, title=self.title, size=(400, 250), style=(wx.MINIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN))


class MyApp (wx.App):
def OnInit(self):
self.frame = MyFrame(None, title='Parent-Frame')
self.frame.Show()
self.SetTopWindow(self.frame)
return True

if __name__ == '__main__':
app = MyApp(0)
app.MainLoop()

Answer

You can also make the second frame modal just like a dialog. Here's your code modified to do just that:

import wx

class MyFrame(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(400, 320), style=(wx.MINIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN))

        # Setting up menu
        filemenu = wx.Menu()
        set_m = filemenu.Append(wx.ID_PREFERENCES, 'Settings', 'Settings')
        # filemenu.Append(US)
        filemenu.AppendSeparator()
        exit_m = filemenu.Append(wx.ID_EXIT)

        # Creating the menubar
        menubar = wx.MenuBar()
        menubar.Append(filemenu, 'Menu')
        self.SetMenuBar(menubar)

        self.Bind(wx.EVT_MENU, self.OnSettings, set_m)

    def OnSettings(self, e):
        SetFrame().Show()

class SetFrame(wx.Frame):
    title = 'Settings'
    def __init__(self):
        wx.Frame.__init__(self, wx.GetApp().TopWindow, title=self.title, size=(400, 250), style=(wx.MINIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN))
        self.Bind(wx.EVT_CLOSE, self.onClose)
        self.MakeModal()

    #----------------------------------------------------------------------
    def onClose(self, event):
        """
        Make the frame non-modal as it closes to re-enable other windows
        """
        self.MakeModal(False)
        self.Destroy()

class MyApp (wx.App):
    def OnInit(self):
        self.frame = MyFrame(None, title='Parent-Frame')
        self.frame.Show()
        self.SetTopWindow(self.frame)
        return True

if __name__ == '__main__':
    app = MyApp(0)
    app.MainLoop()

Note that you have to disable the modality when you close the settings frame to re-enable the other windows. See http://wxpython-users.1045709.n5.nabble.com/making-a-frame-modal-td2363708.html for more information.