Remember MDI? Many people don't. MDI was an early '90s Microsoft innovation, that allowed multiple child windows in an application to be controlled by a single parent window, essentially providing a separate desktop for each application. In most applications, MDI requires all windows in the application to minimize together and maintain the same z-order relative to the rest of the system, which is limiting. We recommend using MDI only in cases where the user expects to see all of the application windows together, such as a game. Figure 8.7 displays a typical MDI environment.
MDI is supported in wxPython by using native widgets under Windows operating systems, and simulating the child windows in other operating systems. Listing 8.8 provides a simple example of MDI in action.
Figure 8.7 An MDI window
Listing 8.8 How to create an MDI window import wx class MDIFrame(wx.MDIParentFrame):
wx.MDIParentFrame._init_(self, None, -1, "MDI Parent", size=(600,400)) menu = wx.Menu()
menu.Append(5000, "&New Window") menu.Append(5001, "E&xit") menubar = wx.MenuBar() menubar.Append(menu, "&File") self.SetMenuBar(menubar)
self.Bind(wx.EVT_MENU, self.OnNewWindow, id=5000) self.Bind(wx.EVT_MENU, self.OnExit, id=5001)
def OnExit(self, evt): self.Close(True)
def OnNewWindow(self, evt):
win = wx.MDIChildFrame(self, -1, "Child Window") win.Show(True)
app = wx.PySimpleApp() frame = MDIFrame() frame.Show() app.MainLoop()
Figure 8.7 An MDI window
The basic concept of MDI is quite simple. The parent window is a subclass of wx.MDIParentFrame, and child windows are added just like any other wxPython widget, except that they are subclasses of wx.MDIChildFrame. The wx.MDIParentFrame constructor is almost identical to wx.Frame, as in the following:
wx.MDIParentFrame(parent, id, title, pos = wx.DefaultPosition, size=wxDefaultSize, style=wx.DEFAULT_FRAME_STYLE | wx.VSCROLL | wx.HSCROLL, name="frame")
One difference is that a wx.MDIParentFrame has scrolling on by default. The wx.MDIChildFrame constructor is identical, except that it does not have the scrolling. As in listing 8.8, adding the child frame is accomplished by creating one, with the parent frame as the parent.
You can change the position and size of all child frames simultaneously by using the parent frame methods Cascade() or Tile(), which mimic the common menu items of the same name. Calling Cascade(), causes the windows to appear one on top of the other, as in figure 8.7, while Tile() makes each window the same size and moves them so they don't overlap. To programmatically move the focus among the child windows, use the parent methods ActivateNext() and ActivatePrevious().
Was this article helpful?