在wx.python中无法访问顶层窗口

时间:2013-04-17 08:17:08

标签: python user-interface wxpython frame

如果在子框架打开时如何使顶部框架无法访问?

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()

3 个答案:

答案 0 :(得分:2)

您可以使用模态对话框,尽管模态对话框会阻止应用程序的其余部分,您可能不希望这样。

要使您的框架像一个不阻止应用程序的模式对话框一样,当您打开子框架时禁用父框架时,请记住在子框架关闭时再次启用父框架。

同样最好在子框架上设置样式wx.FRAME_FLOAT_ON_PARENT,使其保持在父框架的顶部,并将其设置为父框架的中心。

我修改了下面的代码,以便在子框架打开时无法访问顶部框架。

import wx


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

        # 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):
        style = (wx.MINIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX |
                 wx.CLIP_CHILDREN | wx.FRAME_FLOAT_ON_PARENT)
        wx.Frame.__init__(self, wx.GetApp().TopWindow, title=self.title,
                          size=(400, 250), style=style)

        self.CenterOnParent()
        self.GetParent().Disable()

        self.Bind(wx.EVT_CLOSE, self.onClose)

    def onClose(self, event):
        self.Close()
        event.Skip()

    def Close(self):
        self.GetParent().Enable()
        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()

答案 1 :(得分:1)

您也可以像对话框一样制作第二帧模态。以下是您修改的代码:

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()

请注意,必须在关闭设置框架时禁用该模式才能重新启用其他窗口。有关详细信息,请参阅http://wxpython-users.1045709.n5.nabble.com/making-a-frame-modal-td2363708.html

答案 2 :(得分:1)

嵌套模式对话框导致我的应用程序出现问题,所以我最终做了:

self.GetParent().Disable()
self.Enable()
self.Bind(wx.EVT_CLOSE, self.on_close)

def on_close(self, event):
    event.Skip()
    self.GetParent().Enable()
    self.Destroy()

禁用父级也会禁用所有子窗口,但可以重新启用它们。

编辑: 此外,向wx.FRAME_FLOAT_ON_PARENT添加wx.FRAME_NO_TASKBARwx.Frame.__init__样式有助于复制模态对话框的行为