I'm bulding a wxpython GUI.
When I'm running the code all the components are in the left-top corner, on top of each other.
When I resize the window, they align as planned.
The window before resize
The window after resize
How can I fix this?
my code:
class Screen(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title, size=(900,500))
self.SetBackgroundColour("#E4F1FE")
self.Show(True)
self.InitUI()
def InitUI(self):
pnlMain = wx.Panel(self, size=(900,500))
# Setup Font
font = wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT)
font.SetPointSize(9)
# Setup horizontal box sizer
self.bsMain = wx.BoxSizer(wx.HORIZONTAL)
self.bsMain.SetDimension(0,0,900,500)
# Setup LEFT box sizer
self.bsLeft = wx.BoxSizer(wx.VERTICAL)
self.bsLeft.SetMinSize((3*(self.GetSize()[0]/4),self.GetSize()[1]))
# Make add button
btnAdd = wx.Button(pnlMain, label="+", size=(50,50))
# Add all the components to the LEFT sizer
self.bsLeft.Add(btnAdd, flag = wx.ALIGN_BOTTOM | wx.ALIGN_LEFT )
# Setup RIGHT bsMain sizer
self.bsRight = wx.BoxSizer(wx.VERTICAL)
self.bsRight.SetMinSize((self.GetSize()[0]/4,self.GetSize()[1]))
# Make users headline
stUsers = wx.StaticText(pnlMain, label="USERS")
stUsers.SetFont(font)
# Make users list control
lcUsers = wx.ListCtrl(pnlMain,style=wx.LC_REPORT|wx.SUNKEN_BORDER)
lcUsers.Show(True)
lcUsers.InsertColumn(0,"user")
lcUsers.InsertColumn(1,"status")
# Add all the components to the RIGHT sizer
self.bsRight.Add((-1,10))
self.bsRight.Add(stUsers, flag=wx.LEFT | wx.EXPAND | wx.ALIGN_CENTER | wx.ALIGN_CENTRE, border=5)
self.bsRight.Add((-1,10))
self.bsRight.Add(lcUsers, flag=wx.EXPAND)
# Add the vertical sizers to the horizontal sizer
self.bsMain.Add(self.bsLeft)
self.bsMain.Add(self.bsRight)
# Add the vertical sizer to the panel
pnlMain.SetSizer(self.bsMain)
This is a common problem for new wxPython programmers. The solution is almost always a call to the top level sizer's Layout method. Occasionally you'll need to call the top-level parent's Layout instead. In your case, either will work. You can add:
pnlMain.Layout()
or
self.bsMain.Layout()
to the bottom of InitUI method and it should force your widgets to redraw in their correct locations. I've seen some widgets behave badly because they start out with a zero size until their shown. In those cases, I have usually needed to use wx.CallAfter to call Layout. Anyway, here's a complete example using your code:
import wx
class Screen(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title, size=(900,500))
self.SetBackgroundColour("#E4F1FE")
self.Show(True)
self.InitUI()
def InitUI(self):
pnlMain = wx.Panel(self, size=(900,500))
# Setup Font
font = wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT)
font.SetPointSize(9)
# Setup horizontal box sizer
self.bsMain = wx.BoxSizer(wx.HORIZONTAL)
self.bsMain.SetDimension(0,0,900,500)
# Setup LEFT box sizer
self.bsLeft = wx.BoxSizer(wx.VERTICAL)
self.bsLeft.SetMinSize((3*(self.GetSize()[0]/4),self.GetSize()[1]))
# Make add button
btnAdd = wx.Button(pnlMain, label="+", size=(50,50))
# Add all the components to the LEFT sizer
self.bsLeft.Add(btnAdd, flag = wx.ALIGN_BOTTOM | wx.ALIGN_LEFT )
# Setup RIGHT bsMain sizer
self.bsRight = wx.BoxSizer(wx.VERTICAL)
self.bsRight.SetMinSize((self.GetSize()[0]/4,self.GetSize()[1]))
# Make users headline
stUsers = wx.StaticText(pnlMain, label="USERS")
stUsers.SetFont(font)
# Make users list control
lcUsers = wx.ListCtrl(pnlMain,style=wx.LC_REPORT|wx.SUNKEN_BORDER)
lcUsers.Show(True)
lcUsers.InsertColumn(0,"user")
lcUsers.InsertColumn(1,"status")
# Add all the components to the RIGHT sizer
self.bsRight.Add((-1,10))
self.bsRight.Add(stUsers, flag=wx.LEFT | wx.EXPAND | wx.ALIGN_CENTER | wx.ALIGN_CENTRE, border=5)
self.bsRight.Add((-1,10))
self.bsRight.Add(lcUsers, flag=wx.EXPAND)
# Add the vertical sizers to the horizontal sizer
self.bsMain.Add(self.bsLeft)
self.bsMain.Add(self.bsRight)
# Add the vertical sizer to the panel
pnlMain.SetSizer(self.bsMain)
self.bsMain.Layout()
if __name__ == '__main__':
app = wx.App(False)
frame = Screen(None, 'Layout')
app.MainLoop()
Note: I've rarely needed to call Refresh. I think Layout does so automatically.
Related
I've read so many questions similar to this but I'm caving in and making my own because nothing is working. Basically, I want to have my wx.StaticText have vertically centered text while resizing with the window. My understanding is that existing solutions don't work because I care about the background of the StaticText, and so I cannot simply vertically center the label itself in a sizer. I also see that it requires messy subclassing to have a transparent-background StaticText, so overlaying it on a panel sounds difficult.
Here is a minimal example (in my project the sizer has several other things in it):
import wx
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(None, title='Sample')
sizer=wx.BoxSizer(wx.VERTICAL)
label = wx.StaticText(self, -1, 'PLEASE VERTICALLY CENTER ME ;(', style=wx.ALIGN_CENTRE | wx.ST_NO_AUTORESIZE)
label.SetMinSize((300,300))
label.SetBackgroundColour((255,0,0))
sizer.Add(label, 1, wx.EXPAND | wx.ALL, 10)
self.SetSizerAndFit(sizer)
if __name__ == '__main__':
app=wx.App()
frame=MyFrame()
frame.Show()
app.MainLoop()
Despite that, it's hard to accept it's not simple to vertically center text. What is the easiest way to have the text in the label be vertically centered?
Solution:
catalin's answer gave the concept necessary! Here is a full snippet for anyone else who encounters this problem. I added a button below the StaticText to demonstrate the vertical sizer remaining in control. The vertical sizer could be removed altogether if your application doesn't need it.
import wx
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(None, title='Sample')
sizer=wx.BoxSizer(wx.VERTICAL) # "main" sizer
panel = wx.Panel(self) # panel just for centering label
panel.SetBackgroundColour((255,0,0))
label = wx.StaticText(panel, -1, 'PLEASE VERTICALLY CENTER ME ;(', style=wx.ALIGN_CENTRE | wx.ST_NO_AUTORESIZE)
hsizer=wx.BoxSizer(wx.HORIZONTAL) # sizer for the panel
hsizer.Add(label, 1, wx.ALIGN_CENTER_VERTICAL)
panel.SetSizer(hsizer)
sizer.Add(panel, 1, wx.EXPAND)
btn = wx.Button(self, -1, 'Button')
sizer.Add(btn, 0, wx.EXPAND)
self.SetSizerAndFit(sizer)
if __name__ == '__main__':
app=wx.App()
frame=MyFrame()
frame.Show()
app.MainLoop()
In c++ a quick way would look like this:
wxPanel* p = new wxPanel(this); // you don't need to put it in a sizer if it's the only child
p->SetBackgroundColour({ 255, 0, 0 }); // this will be inherited by children
wxStaticText* label = new wxStaticText(p, wxID_ANY, "PLEASE VERTICALLY CENTER ME ;(");
wxSizer* s = new wxBoxSizer(wxHORIZONTAL); // for vertical one, you'd need stretch-spacers, and could not use wxALIGN_CENTER_VERTICAL, see below
s->Add(label, wxSizerFlags(1).Align(wxALIGN_CENTER_VERTICAL));
p->SetSizer(s);
Mind that if you want the text to wrap upon resize, wxStaticText will probably not resize correctly, and you might need to replace it with something else.
Another example of the sizer concept.
The frame is broken up into component parts, with each part assigned its relevant sizer.
The component sizers are then put within a main (self) sizer, to put it all together.
In this case the components are text, that needs to be centered and a set of buttons to the right, vertically stacked.
Obviously, components and arrangements differ but the concept of breaking the design into parts, which is then assembled for final presentation, remains the same.
Indeed, complicated components often need to have the same principle applied, leaving you with a series of sub-assemblies before the final one, in the main sizer.
import wx
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(None, title='Sample')
mainsizer=wx.BoxSizer(wx.HORIZONTAL) # "main" sizer
tsizer=wx.BoxSizer(wx.HORIZONTAL) # "text" sizer
bsizer=wx.BoxSizer(wx.VERTICAL) # "button" sizer
panel = wx.Panel(self) # panel for label
button_panel = wx.Panel(self) # panel for buttons
panel.SetBackgroundColour((190,0,0))
button_panel.SetBackgroundColour((160,0,0))
label = wx.StaticText(panel, -1, 'PLEASE VERTICALLY CENTER ME ;(')
btn1 = wx.Button(button_panel,-1, 'Button 1')
btn2 = wx.Button(button_panel,-1, 'Button 2')
btn3 = wx.Button(button_panel,-1, 'Button 3')
btn4 = wx.Button(button_panel,-1, 'Button 4')
tsizer.AddSpacer(10)
tsizer.Add(label, 0, wx.CENTER)
tsizer.AddSpacer(10) # Ensure gap between text and buttons
bsizer.Add(btn1)
bsizer.Add(btn2)
bsizer.Add(btn3)
bsizer.Add(btn4, 0, wx.BOTTOM, 35) # With space below
panel.SetSizer(tsizer)
button_panel.SetSizer(bsizer)
mainsizer.Add(panel, proportion=1, flag=wx.EXPAND) # panel to grow when resized
mainsizer.Add(button_panel, proportion=0, flag=wx.EXPAND) # panel to fill available space
self.SetSizerAndFit(mainsizer)
if __name__ == '__main__':
app=wx.App()
frame=MyFrame()
frame.Show()
app.MainLoop()
I am writing a small app that works very well on linux, but I have some trouble on windows. Here is the code sample:
import wx
#####################################################################
class Main(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="StackOverflow", pos=wx.DefaultPosition, size=(800,600))
self.SetMinSize( self.GetSize() )
p = wx.Panel(self)
nb = wx.Notebook(p)
page1 = AddToCollection(nb)
page2 = CollectionStatistics(nb)
nb.AddPage(page1, "Page 1")
nb.AddPage(page2, "Page 2")
# finally, put the notebook in a sizer for the panel to manage
# the layout
sizer = wx.BoxSizer()
sizer.Add(nb, 1, wx.EXPAND)
p.SetSizer(sizer)
#########################################################################
class CollectionStatistics(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
#########################################################################
class AddToCollection(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.v1_qty_list = [str(x) for x in range(9)]
self.v2_qty_list = [str(x) for x in range(9)]
self.sizername = wx.GridBagSizer(5, 5)
self.sizername.AddGrowableCol(0,0)
self.name_txt = wx.StaticText(self, label="Enter Name :")
self.sizername.Add(self.name_txt,(2,0),(1,1),wx.EXPAND)
self.name = wx.TextCtrl(self,style=wx.TE_PROCESS_ENTER,value=u"")
self.sizername.Add(self.name,(3,0),(1,1),wx.EXPAND)
self.Bind(wx.EVT_TEXT_ENTER, self.OnPressEnter, self.name)
self.SetSizerAndFit(self.sizername)
self.SetSizeHints(-1,self.GetSize().y,-1,self.GetSize().y )
##########################################################################
def OnPressEnter(self,event):
self.selected_name = self.name.GetValue()
self.AddToCol()
##########################################################################
def AddToCol(self):
self.sizerAdd = wx.GridBagSizer(5, 5)
self.sizerAdd.AddGrowableCol(0, 0)
self.name.Enable(False)
### Expansion
self.expansion = wx.Choice(self, -1, choices=['test 1', 'test 2'])
self.expansion.SetSelection(0)
self.sizerAdd.Add(self.expansion,(5,0),(1,6),wx.EXPAND)
### Quantities txt
self.v1_txt = wx.StaticText(self, label="V1 Quantity :")
self.sizerAdd.Add(self.v1_txt,(7,0),(1,1),wx.EXPAND)
self.v2_txt = wx.StaticText(self, label="V2 Quantity :")
self.sizerAdd.Add(self.v2_txt,(8,0),(1,1),wx.EXPAND)
### Quantities choices
self.v1_qty = wx.Choice(self, -1, choices=self.v1_qty_list)
self.v1_qty.SetSelection(0)
self.sizerAdd.Add(self.v1_qty,(7,5),(1,1),wx.EXPAND)
self.v2_qty = wx.Choice(self, -1, choices=self.v1_qty_list)
self.v2_qty.SetSelection(0)
self.sizerAdd.Add(self.v2_qty,(8,5),(1,1),wx.EXPAND)
### Ok Button
self.Add_btn = wx.Button(self, -1, "Add")
self.Add_btn.Bind(wx.EVT_BUTTON, self.OnAdd)
self.sizerAdd.Add(self.Add_btn,(9,5),(1,1),wx.EXPAND)
### Reset Button
self.Reset_btn = wx.Button(self, -1, "Reset")
self.Reset_btn.Bind(wx.EVT_BUTTON, self.OnResetPanel)
self.sizerAdd.Add(self.Reset_btn,(9,4),(1,1),wx.EXPAND)
self.SetSizerAndFit(self.sizerAdd)
self.SetSizeHints(-1,self.GetSize().y,-1,self.GetSize().y )
######################################################################
def OnResetPanel(self,event):
### Kill all children
self.expansion.Destroy()
self.v1_txt.Destroy()
self.v1_qty.Destroy()
self.v2_txt.Destroy()
self.v2_qty.Destroy()
self.Add_btn.Destroy()
self.Reset_btn.Destroy()
### Reinitialise sizer
self.name.Enable(True)
self.name.SetValue("")
######################################################################
def OnAdd(self,event):
print 'Add'
self.OnResetPanel(self)
######################################################################
######################################################################
if __name__ == "__main__":
app = wx.App()
Main().Show()
app.MainLoop()
Basically, I have a TextCtrl in a first sizer which is waiting for an entry. Once the user hits enter, several objects appear in a second sizer.
The issue on windows seems to come from the use of the two gridbagsizers (sizername and sizerAdd). After pressing enter (waited event in the __init__), the objects defined within the sizerAdd do not appear. When I extend the window where the script is running, these objects appear magically !
Any idea ?
EDIT : The code is now runnable
I think the problem in your code is these two lines at the end of your AddToCol method:
self.SetSizerAndFit(self.sizerAdd)
self.SetSizeHints(-1,self.GetSize().y,-1,self.GetSize().y )
At this point, you're changing the sizer of the AddToCollection panel from self.sizername to self.sizerAdd. The Enter Name: label and the textbox however are still within the self.sizername sizer. However, this sizer isn't the sizer for any window, nor has it been added to any other sizer.
Generally, in wxPython, every sizer should be set as the sizer for a window, or be added to another sizer. This other sizer would then be the sizer for a window, or be contained within another sizer, and so on. In your case, your self.sizername sizer ends up being neither, and in this situation I would expect unpredictable behaviour. If your code works on Linux then I would say that it happens to work by accident.
I can think of a few things you could do here:
Add self.sizerAdd as a child of self.sizername. This can be done by replacing the two lines above with
self.sizername.Add(self.sizerAdd,(4,0),(1,1),wx.EXPAND)
self.sizername.Layout()
In AddToCol, add the widgets directly to the self.sizername sizer instead of adding them to self.sizerAdd.
Create a wx.BoxSizer() with vertical orientation, set that to be the sizer for the AddToCollection panel, and add the self.sizername and self.sizerAdd sizers to your BoxSizer.
In all three cases, after creating the new widgets you will need to call the Layout() method on the top-level sizer, be it either self.sizername or the top-level BoxSizer. The code snippet under option 1 includes this line already.
Additionally, you may need to modify your OnResetPanel() method. If you chose options 1 or 3, you will need to remove the self.sizerAdd sizer from whichever sizer you added it to. For example, in option 1, you would add the line
self.sizername.Remove(self.sizerAdd)
Another approach would be for your AddToCol method to create all the widgets within a Panel and add that to the main panel at the end. Your AddToCol method would then need to create a child panel, add the extra controls as children of this panel instead of the main panel (self), set the sizer of the child panel to self.sizerAdd and finally add this panel to the self.sizername sizer.
def AddToCol(self):
self.sizerAdd = wx.GridBagSizer(5, 5)
self.sizerAdd.AddGrowableCol(0, 0)
self.name.Enable(False)
self.child_panel = wx.Panel(self)
### Expansion
self.expansion = wx.Choice(self.child_panel, -1, choices=['test 1', 'test 2'])
self.expansion.SetSelection(0)
self.sizerAdd.Add(self.expansion,(5,0),(1,6),wx.EXPAND)
# Create other widgets as before but with the parent set to self.child_panel
# instead of self.
self.child_panel.SetSizer(self.sizerAdd)
self.sizername.Add(self.child_panel,(4,0),(1,1),wx.EXPAND)
self.sizername.Layout()
You would then also need to replace the line
self.sizername.Remove(self.sizerAdd)
in OnResetPanel() with the two lines:
self.sizername.Remove(self.child_panel)
self.child_panel.Destroy()
One thing which bugged me about my approach 1 above was that I saw the widgets briefly appear in the top-left corner before appearing in the correct place. This adaptation fixes this problem and so makes the GUI behave itself a bit better. I couldn't reproduce your black area issue you mention in your comment, but hopefully this approach fixes your problem as well.
I uses a WrapSizer in order to have an automatic layout (as thumbnail gallery) like this (see screenshot on the left) :
I would like that if there are two many elements, a (vertical only)-ScrollBar is added on the panel (see right screenshot). How to add such a vertical scrollbar to a panel using a WrapSizer?
I tried by mixing WrapSizer and ScrolledPanel, but I cannot get the desired layout.
class MyPanel(scrolled.ScrolledPanel):
def __init__(self, parent):
scrolled.ScrolledPanel.__init__(self, parent)
self.SetBackgroundColour('#f8f8f8')
sizer = wx.WrapSizer()
self.SetupScrolling()
# add some widgets btn1, btn2, etc. in the WrapSizer
sizer.Add(btn1, 0, wx.ALL, 10)
sizer.Add(btn2, 0, wx.ALL, 10)
Solution:
reset the width of the scroll panel virtual size to the displayable size.
import wx
import wx.lib.scrolledpanel as scrolled
class MyPanel(scrolled.ScrolledPanel):
def __init__(self, parent):
scrolled.ScrolledPanel.__init__(self, parent, style=wx.VSCROLL)
self.SetBackgroundColour('#f8f8f8')
self.sizer = wx.WrapSizer()
self.SetupScrolling(scroll_x = False)
self.parent = parent
self.addButton(self.sizer , 10)
self.SetSizer(self.sizer )
self.Bind(wx.EVT_SIZE, self.onSize)
def onSize(self, evt):
size = self.GetSize()
vsize = self.GetVirtualSize()
self.SetVirtualSize((size[0], vsize[1]))
evt.Skip()
def addButton(self, sizer, num):
for i in range(1, num):
btn =wx.Button( self, wx.ID_ANY, "btn"+str(i), wx.DefaultPosition, wx.DefaultSize, 0 )
sizer.Add(btn, 0, wx.ALL, 10)
if __name__=='__main__':
app = wx.App(redirect=False)
frame = wx.Frame(None)
MyPanel(frame)
frame.Show()
app.MainLoop()
It looks like you just forgot to include
self.SetSizer(sizer)
Since the WrapSizer takes the whole frame, I think that will work. Also, instead of SetupScrolling, you can use
self.SetScrollRate(horiz, vert)
to specify the increment (in pixels, i think) of the scroll, and that should work.
I can't test it here right now though, and WrapSizers are a little weird - they sometimes have trouble figuring out their proper size. You may need to wrap it in a BoxSizer going the other direction.
I have created a pop up window, but the TextCtrl is not fully expanded to fill up the window. It works great if I use StaticText instead, (but if content too large then I would need the scroll bar, that is why I am using TextCtrl now). Please provide some guidance.
self.description = WindowPopup(self, wx.SIMPLE_BORDER, content)
btn = event.GetEventObject()
dw = wx.DisplaySize()[0]
width = self.description.GetSize()[0]
y = btn.ClientToScreen((0,0))[1]
height = btn.GetSize()[1]
x = dw - width - 20 - 10
self.description.Position((x, y), (0, height))
self.description.Show(True)
class WindowPopup(wx.PopupWindow):
""" Pops up a window to provide description for the selection """
def __init__(self, parent, style, content):
wx.PopupWindow.__init__(self, parent, style)
self.SetSize((700, 287))
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
st = wx.TextCtrl(self, -1, style = wx.TE_MULTILINE | wx.TE_READONLY)
st.SetValue(content)
sizer.Add(st, 0, wx.EXPAND)
panel.SetSizer(sizer)
I suspect your problem is that the panel is not as big as the popupwindow ... so even though the textfield is expanding to fill its sizer area it is not filling the popup its self.
try using something like
def __init__(...):
...
self.SetMinSize((700,287))
sizer2 = wx.BoxSizer()
sizer2.Add(panel)
self.SetSizer(sizer2)
also make sure that you are calling layout on it at some point (note this is totally untested... so it may need some tweeks, or even worse just be wrong...)
The actual answer is:
sizer = wx.BoxSizer(wx.VERTICAL)
st = wx.TextCtrl(self, -1, style = wx.TE_MULTILINE | wx.TE_READONLY, size = (500, 174))
st.SetValue(content)
self.SetSize((500, 174))
sizer.Add(st, 0, wx.EXPAND)
self.SetSizer(sizer)
self.Layout()
self.Show(True)
Credits to Joran for noticing Layout().
PopupWindow does not require an additional panel, because the window itself can have sizer set to it. This has been realized by using the wxPython Widget Inspection Tool.
Make sure TextCtrl and PopupWindow have the same size.
I have a figure canvas in a ScrolledPanel in a Panel. I want to change the size of the figure canvas. E.g.
mplFigure.set_figheight(1.0)
someobject.soSomethingThatResizeItAll
How can I do this?
Thanks
David
Here's my construction code.
panel = wx.Panel(self) # we put the scrollablePanel in the panel so later on we can do fit to window sizing too (i.e. by removing the scrollablePanel)
# create a scrollablePanel to hold the canvas
scrollablePanel = ScrolledPanel(parent=panel, id=wx.ID_ANY, name="scrolledPanel", style=wx.ALWAYS_SHOW_SB)
scrollablePanel.SetupScrolling()
scrollablePanel.SetBackgroundColour(wx.Colour(128,128,128))
# create mpl canvas and figure
mplFigure = Figure(figsize=A6H, facecolor="white") #, edgecolor="black")
mplFigureCanvas = FigureCanvasWxAgg(parent=scrollablePanel, id=wx.ID_ANY, figure=mplFigure)
#mplFigureCanvas.SetWindowStyle=wx.SIMPLE_BORDER # not sure if this will have any affect?
#mplFigureCanvas.SetBackgroundColour(wx.Colour(0,0,0))
# center the FigureCanvas inthe scrollablePanel
sizer1 = wx.BoxSizer(wx.VERTICAL)
sizer1.Add(mplFigureCanvas, proportion=0, flag=wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, border=8)
sizer2 = wx.BoxSizer(wx.HORIZONTAL)
sizer2.Add(sizer1, proportion=1, flag=wx.ALIGN_CENTER_VERTICAL)
scrollablePanel.SetSizer(sizer2)
# create mpl toolbar
#mplToolbar = NavigationToolbar2Wx(mplFigureCanvas)
#mplToolbar.Realize() # needed to support Windows systems
# use another sizer to add the scrollablePanel to the main panel
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(scrollablePanel, 1, wx.LEFT | wx.EXPAND)
#sizer.Add(mplToolbar, 0, wx.LEFT | wx.EXPAND)
#mplToolbar.Show()
panel.SetSizer(sizer)
Well I now have some horrible code that gets the result but it's not pretty.
mplFigure.set_size_inches(sizeInInches)
l,b,w,h = mplFigure.bbox.bounds
w = int(math.ceil(w))
h = int(math.ceil(h))
mplCanvas.SetInitialSize(size=wx.Size(w, h))
size = panel.Size
panel.SetSize(wx.Size(size.x, size.y-1))
panel.SetSize(wx.Size(size.x, size.y))
An improvement would be welcome.
-- DB
Well I've found part of the answer.
mplFigureCanvas.SetSize(...) does it initially but as soon as I resize the frame it goes back to the original size.
-- DB
If I understand your question correctly I think you'll want to set up your panels differently. I would put the mpl_canvas in a wx.Panel and then put that panel into the ScrolledPanel. Then to enlarge/shrink the canvas just update the MinSize of the panel (panel.SetMinSize()).