My wxBoxList is too high (my own menu implementation) - example included

Hello!

I need special menu control (menu with selection, mayby with another
gadgets:) ) and i write my own class with wxDialog and wxListBox
inside. But this list is always to high…
I need method like FitInside but for items inside list. When list have
3 items and each have 13 pix then list must be about 3*13 pix high?
But list have mayby some space between items? I can use DC i measure each lists item but mayby is anothe, better way?
I write here some code with mouse event - when user click outside “menu” then i close dialog.

################################## E X A M P L E

import wx

my menu control implementation

···

###############################################################################
class MyMenu(wx.Dialog):
###############################################################################
def init(self, parent, choices=None):
wx.Dialog.init(self, parent, -1, style = wx.NO_3D)
self.list = wx.ListBox(self, -1, style=wx.NO_BORDER)
self.list.Bind(wx.EVT_LISTBOX_DCLICK, self.OnListDblClick)
self.list.Bind(wx.EVT_KEY_DOWN, self.OnListKeyDown)

self.list.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
self.list.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
self.list.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
self.list.Bind(wx.EVT_CLOSE, self.OnClose)

self.SetChoices(choices)
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
self.mainSizer.Add(self.list, 1, wx.EXPAND|wx.ALL, 1)
self.SetSizer(self.mainSizer)

def Popup(self, pos):
self.SetPosition(pos)
self.list.CaptureMouse()
self.Fit()
return self.ShowModal()

def OnKillFocus(self, event):
event.Skip()
if self.list.HasCapture():
self.list.ReleaseMouse()

def OnSetFocus(self, event):
event.Skip()
if not self.list.HasCapture():
self.list.CaptureMouse()

def OnMouse(self, event):
event.Skip()
if event.LeftDown():
pos = event.GetPosition()
rct = self.list.GetRect()
if not rct.Inside(pos):
event.Skip(False)
self.Close()

def OnClose(self, event):
if self.list.HasCapture():
self.list.ReleaseMouse()
event.Skip()

def SetChoices(self, choices):
self.list.Clear()
for item1 in choices:
self.list.Append(item1)

def GetSelString(self):
sel_indx = self.list.GetSelection()
return self.list.GetString(sel_indx)

def GetString(self, index):
return self.list.GetString(index)

def SetSelection(self, index):
self.list.SetSelection(index)

def GetSelection(self):
return self.list.GetSelection()

def OnListDblClick(self, event):
event.Skip(False)
self.Close()
self.SetReturnCode(wx.ID_OK)

def OnListKeyDown(self, event):
event.Skip()
key_code = event.m_keyCode
if key_code in (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER):
self.Close()
self.SetReturnCode(wx.ID_OK)
elif key_code == wx.WXK_ESCAPE:
self.Close()
self.SetReturnCode(wx.ID_CANCEL)
###############################################################################
###############################################################################

test APP

ID_B1 = wx.NewId()
ID_B2 = wx.NewId()
ID_B3 = wx.NewId()

class TestDialog(wx.Dialog):
def init(self):
wx.Dialog.init(self, None, -1, “Test dialog”, style=wx.DEFAULT_DIALOG_STYLE)
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
b1 = wx.Button(self, ID_B1, “Menu1”)
b2 = wx.Button(self, ID_B2, “Menu2”)
b3 = wx.Button(self, ID_B3, “Menu3”)
self.selTab = [0,0,0]
mainSizer.Add(b1, 0, wx.ALL, 20)
mainSizer.Add(b2, 0, wx.ALL, 20)
mainSizer.Add(b3, 0, wx.ALL, 20)
self.Bind(wx.EVT_CLOSE, self.OnClose)
self.Bind(wx.EVT_BUTTON, self.OnBtn)
self.SetSizer(mainSizer)
self.Fit()

def OnBtn(self, event):
btn_id = event.GetEventObject().GetId()
btn_indx = btn_id - ID_B1
menu = None
if btn_id == ID_B1:
menu = MyMenu(self, [“Item #11”, “Item #12”, “Item #13”])
elif btn_id == ID_B2:
menu = MyMenu(self, [“Item #21”, “Item #22”, “Item #23”])
elif btn_id == ID_B3:
menu = MyMenu(self, [“Item #31”, “Item #32”, “Item #33”])
if menu:
menu.SetSelection(self.selTab[btn_indx])
but_pos = self.ClientToScreen(event.GetEventObject().GetPosition())
mr = menu.Popup(but_pos)
if(mr==wx.ID_OK):
sel_indx = menu.GetSelection()
event.GetEventObject().SetLabel(menu.GetString(sel_indx))
self.selTab[btn_indx] = sel_indx
menu.Destroy()

def OnClose(self, event):
self.Destroy()

if name == ‘main’:
class MyApp(wx.App):
def OnInit(self):
wx.InitAllImageHandlers()
dlg = TestDialog()
dlg.Centre();
dlg.Show(True);
self.SetTopWindow(dlg);
return True

app = MyApp(False)
app.MainLoop()

Wojtek P wrote:

Hello!

I need special menu control (menu with selection, mayby with another gadgets:) ) and i write my own class with wxDialog and wxListBox inside. But this list is always to high...
I need method like FitInside but for items inside list. When list have 3 items and each have 13 pix then list must be about 3*13 pix high?
But list have mayby some space between items? I can use DC i measure each lists item but mayby is anothe, better way?

You can call the listbox's GetBestSize method to get a size that is dependent on the number of items in the control, but I think for wxListBox it clamps the value to a minimum of 3 lines, and also to some reasonable maximum size.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!