1

I am attempting to build a series of menus into my traitsui visualization program application. My GUI is comprised of a sequence of panels which all use different model objects, which are all displayed in the main GUI using InstanceEditors. This has numerous benefits including that the panels can just be garbage collected and rebuilt at any time (which is important for mayavi visualizations since mayavi is buggy, often it is better to just throw away the scene and start over after the user makes lots of changes).

I am having the problem that Menus do not show up in any of the subpanels in my GUI.

Here is a minimal working example.

from traits.api import HasTraits, Str, Instance
from traitsui.api import Menu, View, MenuBar, Action, Item, InstanceEditor

class Panel(HasTraits):

    field = Str('placeholder_variable')
    stuff_action = Action(name='Do stuff', action='do_stuff')

    view = View(
        Item('field'),
        menubar = MenuBar( Menu( stuff_action, name='Menu')),
    )

    def do_stuff(self):
        print '400'

class Application(HasTraits):
    panel = Instance(Panel, ())

    view = View(
        Item('panel', editor=InstanceEditor(), style='custom'))

Application().configure_traits()

The expected behavior is that the calls Panel().configure_traits() and Application().configure_traits() result in the same GUI, with both a functional menu (with one item called "Do stuff" that prints 400 when clicked) and a string that can be edited.

The actual behavior I am seeing is that the panel GUI has both the string and the menu, while the application GUI has the string but the menu does not appear.

Is there a way to make the menu appear as a GUI widget from inside an InstanceEditor?

aestrivex
  • 5,170
  • 2
  • 27
  • 44

1 Answers1

2

AFAIK, TraitsUI will not support a MenuBar in a sub-view. You may have better success with a toolbar, but both a MenuBar and a ToolBar will need to be defined in Application's view. I got the following minimal UI to work with a couple of tweaks:

from traits.api import HasTraits, Str, Instance, Event
from traitsui.api import View, Item, InstanceEditor
from traitsui.menu import Action, Menu, MenuBar, ToolBar

stuff_action = Action(name='Do stuff', action='do_stuff')

class Panel(HasTraits):
    field = Str('placeholder_variable')
    do_stuff_event = Event

    view = View(Item('field'))

class Application(HasTraits):
    panel = Instance(Panel, ())

    def do_stuff(self):
        print '400'

traits_view = View(
    Item(
        'panel',
        editor=InstanceEditor(),
        style='custom',
        show_label=False,
    ),
    menubar=MenuBar(
        Menu(stuff_action, name='Menu'),
    ),
    toolbar=ToolBar(stuff_action),
    resizable=True,
)

app = Application()
app.configure_traits(view=traits_view)

Here's how it looked for me on Mac OS with Qt4 backend:

enter image description here

enter image description here

Tim D
  • 1,645
  • 1
  • 25
  • 46
  • Yes adding the menu to the outermost panel is not a problem technically. But it would be much more convenient design and maybe more straightforward for the user I think if the subpanels had their own menus related to doing various functions inside the subpanels, rather than having the code for handling actions in one giant menubar in the outermost GUI. – aestrivex Aug 19 '15 at 18:31
  • Mini-menus belonging to a sub-view would break a standard GUI convention (menus and toolbars belong to the application). You could certainly add buttons to a nested view, though. – Tim D Aug 20 '15 at 01:33
  • That is what the GUI looked like in past cycles, the subpanels were cluttered with buttons. But as I have added more and more functions there have just gotten to be, too many buttons. – aestrivex Aug 20 '15 at 14:57