Search code examples
pythonwindowswxpythondelaymenubar

Why is MenuBar item delayed in wxPython in Windows, while instant in OS X?


Please refer to the stripped down example script below. When I run this in OS X the menubar behaves exactly like you'd expect it to. In Windows however there is a noticeable lag (~4s on my 2GHz Core 2 Duo) of the rendering of the 'Slow' menu item. This doesn't feel right at all, to have an application show the good old (Not Responding) warning isn't exactly the behavior you'd expect after clicking around in a menu.

Has anyone run into this problem before? Am I doing something wrong on Windows side?

As far as versions go, I tested both with the latest stable, 2.8.12.1, and development, 2.9.2.1, and I am running Python 2.7.

import wx
from operator import itemgetter
from itertools import groupby

class MainFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title='Hello', size=(1150,700))
        self.panel = wx.Panel(self, -1)
        file_menu = wx.Menu()
        open_item = file_menu.Append(-1, 'Open Something')
        self.slow_menu = wx.Menu()
        another_menu = wx.Menu()
        another_item = another_menu.Append(-1, 'Something')
        more_menu = wx.Menu()
        more_item = more_menu.Append(-1, 'Else')
        self.menu_bar = wx.MenuBar()
        self.menu_bar.Append(file_menu, 'File')
        self.menu_bar.Append(self.slow_menu, 'Slow')
        self.menu_bar.Append(another_menu, 'Fake')
        self.menu_bar.Append(more_menu, 'Hello')
        self.SetMenuBar(self.menu_bar)
        self.setup_slow_menu()
        self.Bind(wx.EVT_CLOSE, self.OnClose)
    def OnClose(self, event):
        self.Destroy()
    def OnDud(self, event):
        pass
    def setup_slow_menu(self):
        names = """
        James    Christopher    Ronald        Mary    Lisa    Michelle
        John     Daniel  Anthony         Patricia     Nancy   Laura
        Robert   Paul     Kevin       Linda   Karen   Sarah
        Michael  Mark     Jason       Barbara     Betty   Kimberly
        William  Donald   Jeff        Elizabeth   Helen   Deborah
        David    George   Jennifer    Sandra
        Richard  Kenneth Maria    Donna
        Charles  Steven  Susan    Carol
        Joseph   Edward  Margaret     Ruth
        Thomas   Brian   Dorothy      Sharon""".split()
        some_data = ['red','blue','white','orange','brown']
        some_more_data = ['socks','pants','shirts','gloves','hats','red','blue','white','orange','brown']
        subs = ['Bla', 'Blabla']
        subsubs = []
        for name in names[:25]:
            subsubs.append((subs[0], name))
        for name in names[25:]:
            subsubs.append((subs[1], name))
        for sub in subs:
            sub_menu = wx.Menu()
            self.slow_menu.AppendMenu(-1, sub, sub_menu)
            for sub, subsub in [r for r in subsubs if r[0]==sub]:
                subsub_menu = wx.Menu()
                sub_menu.AppendMenu(-1, subsub, subsub_menu)
                for i in xrange(30):
                    subsubsub_menu = wx.Menu()
                    subsub_menu.AppendMenu(-1, str(i), subsubsub_menu)
                    for label in some_more_data:
                        menu_item = wx.MenuItem(subsubsub_menu, id=wx.NewId(), text=label)
                        subsubsub_menu.AppendItem(menu_item)
                        self.Bind(wx.EVT_MENU, self.OnDud, id=menu_item.GetId())
                for label in some_data:
                    menu_item = wx.MenuItem(subsub_menu, id=wx.NewId(), text=label)
                    subsub_menu.AppendItem(menu_item)
                    self.Bind(wx.EVT_MENU, self.OnDud, id=menu_item.GetId())
            for label in some_data:
                menu_item = wx.MenuItem(sub_menu, id=wx.NewId(), text=label)
                sub_menu.AppendItem(menu_item)
                self.Bind(wx.EVT_MENU, self.OnDud, id=menu_item.GetId())
        for label in some_data:
            menu_item = wx.MenuItem(self.slow_menu, id=wx.NewId(), text=label)
            self.slow_menu.AppendItem(menu_item)
            self.Bind(wx.EVT_MENU, self.OnDud, id=menu_item.GetId())

if __name__ == "__main__":
    app = wx.PySimpleApp()
    frame = MainFrame()
    frame.Show()
    app.MainLoop()

Solution

  • I posted this on the wxPython list later on, and got this reply. Nothing wrong really, just XP being XP that's all.