如何在wxPython中管理动态的,更改主菜单?

时间:2012-12-01 00:34:49

标签: python wxpython

我正在wxPython中编写基于文档的应用程序,我的意思是用户可以在多个窗口或选项卡中一次打​​开多个文档。有多种文档,文档都可以处于不同的“状态”,这意味着主菜单中应该有不同的菜单选项。

我知道如何使用wx.EVT_UPDATE_UI事件禁用和启用菜单项,但我无法弄清楚如何根据当前具有焦点的文档大幅改变结构和内容的主菜单。我的主要问题之一是主菜单是在顶层窗口中创建的,它必须调用尚未创建的大孩子和曾祖母的方法。


受挫的例子;当打开“JPEG”类型的文档时,主菜单应如下所示:

File      Edit      Compression     Help

当用户将焦点(CTRL + Tab)切换到“PDF”类型的文档时,主菜单应更改为:

File      Edit      PDF     Publish     Help

“编辑”菜单应包含“JPEG”文档聚焦时的一些不同选项。


当前我只是在顶级窗口中的一个名为create_main_menu的函数中创建菜单,文档面板无法控制它。有什么必要推出我上面描述的主菜单方案,特别是在wxPython中?

2 个答案:

答案 0 :(得分:1)

我已经想出了一个非常干净的方法来做到这一点。首先,我创建了我的“基本”主菜单栏,其中包含文件帮助菜单项。然后我定义了一个类EditorPanel而不是wx.Panel的子类,并定义了方法bind_main_menu_barrelease_main_menu_bar。当面板聚焦时,这些方法中的第一个接收主菜单栏,并向其添加一些项目。这是我的一个实现:

def bind_main_menu_bar(self, main_menu_bar):
    main_frame = wx.GetApp().GetTopWindow()

    self.main_menu_bar = main_menu_bar

    # Create the edit menu.
    self.edit_menu = edit_menu = shared.create_menu([
        (const.ID_UNDO, self.LABEL_UNDO_EMPTY),
        (const.ID_REDO, self.LABEL_REDO_EMPTY)
    ])

    # Create the tools menu.
    self.tools_menu = tools_menu = shared.create_menu([
        (const.ID_SELECT_ADDRESS_COLUMNS, 'Select address columns...'),
        (),
        (const.ID_VALIDATE_ADDRESSES, 'Validate selected addresses'),
        (const.ID_VALIDATE_ALL_ADDRESSES, 'Validate all addresses')
    ])

    # Bind some menu event handlers to the main frame.
    main_frame.Bind(wx.EVT_MENU, self.on_menu)
    main_frame.Bind(wx.EVT_UPDATE_UI, self.on_menu_update)

    # Insert the new menus into the main menu bar.
    main_menu_bar.Insert(1, edit_menu, 'Edit')
    main_menu_bar.Insert(2, tools_menu, 'Tools')

现在,当打开该编辑器面板时,主菜单会收到一个编辑菜单和一个绑定到EditorPanel中事件处理程序的工具菜单,这非常方便。当编辑器失去焦点时,将调用release_main_menu_bar方法,该方法应将主菜单栏恢复为原始状态。这是上面代码的对应部分:

def release_main_menu_bar(self):
    main_frame = wx.GetApp().GetTopWindow()

    # Unbind the menu event handlers from the main frame.
    main_frame.Unbind(wx.EVT_MENU, handler=self.on_menu)
    main_frame.Unbind(wx.EVT_UPDATE_UI, handler=self.on_menu_update)

    # Remove the edit and tools menu from the main menu bar.
    self.main_menu_bar.Remove(1)
    self.main_menu_bar.Remove(1)

    # Reset the fields used for the menu.
    self.edit_menu = None
    self.tools_menu = None
    self.main_menu_bar = None

因此,每个想要编辑主菜单的编辑器都必须对这两种方法进行子类化,并且它们具有完全控制权。主框架将监视用户何时在编辑器之间切换并相应地调用方法。最大的问题是找出编辑小组何时收到并失去焦点,这是我的另一个问题的主题:How do I monitor when wx.Panel receives and loses focus?

答案 1 :(得分:0)

使用标准wx.Menu执行此操作的唯一方法可能是销毁并重新创建整个菜单栏。你可能能够隐藏它。无论哪种方式,我认为最简单的方法是组合一组方法来按需创建每个菜单栏。然后你可以摧毁一个并创造另一个。

你可能也会看看FlatMenu,因为它是纯Python并且更容易破解。