1

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

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


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

文件编辑压缩帮助

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

文件编辑 PDF 发布帮助

并且“编辑”菜单应该包含一些与“JPEG”文档成为焦点时不同的选项。


当前我只是create_main_menu在顶层窗口中调用的函数中创建菜单,文档面板无法控制它。要实现我上面描述的那种主菜单方案,特别是在 wxPython 中,需要什么?

4

2 回答 2

2

我想出了一个非常干净的方法来做到这一点。首先,我创建了我的“基本”主菜单栏,其中包含文件帮助菜单项。然后我定义了一个类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')

现在,当打开该编辑器面板时,主菜单会收到一个 Edit 菜单和一个绑定到事件处理程序的 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

所以每个想要编辑主菜单的编辑器只需要继承这两个方法,他们就可以完全控制。主框架将监视用户何时在编辑器之间切换并相应地调用方法。最大的问题是要弄清楚编辑器面板何时接收和失去焦点,这是我的另一个问题的主题:如何监控 wx.Panel 何时接收和失去焦点?

于 2012-12-03T21:36:19.340 回答
0

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

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

于 2012-12-03T16:46:58.270 回答