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


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

3 回答 3

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()
于 2013-04-17T12:03:58.800 回答
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

于 2013-04-17T14:39:28.470 回答
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_PARENTwx.FRAME_NO_TASKBAR样式wx.Frame.__init__可以帮助复制模态对话框的行为

于 2016-07-24T12:41:54.147 回答