Question

I have MyPanel of size (1200,800) which is embedded in a parent MainPanel (whose size can change with the size of the MainFrame) :

import wx

class MyPanel(wx.Panel):   # panel embedded in the main panel
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1, size=(1200,800))
        sizer = wx.BoxSizer(wx.VERTICAL)
        bmp = wx.BitmapFromImage(wx.Image('background.png', wx.BITMAP_TYPE_PNG))  
        myimg = wx.StaticBitmap(self, -1, bmp)
        sizer.Add(myimg, 0, wx.SHAPED, 10)

class MainPanel(wx.Panel):   # main panel embedded in the main frame
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1)
        self.mypanel = MyPanel(self)

class MainFrame(wx.Frame):  # main frame window
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, -1, title, size=(800,600))
        self.panel = MainPanel(self)
        self.Show()

app = wx.App(0)
frame = MainFrame(None, 'Test')
app.MainLoop()

How is it possible to automatically rescale MyPanel so that it fits in the parent MainPanel , keeping its aspect ratio ?

Remark : I am looking for a behaviour close to Windows's standard photo viewer : when the window is resized, the image is rescaled to fit in the parent window.

enter image description here

Was it helpful?

Solution

Just apply my previous answer to the panel that you want to maintain the aspect ration on. Not a 100% clear on the exact behavior you want but this should get you close enough.

import wx

    class MyPanel(wx.Panel):   # panel embedded in the main panel
        def __init__(self, parent):
            wx.Panel.__init__(self, parent, -1)
            sizer = wx.BoxSizer(wx.VERTICAL)
            txt = wx.StaticText(self, label="Missing Bitmap");
            sizer.Add(txt, 0, wx.SHAPED, 10)

            self.SetInitialSize((1200, 800))
            self.BackgroundColour = wx.RED
            self.Sizer = sizer

            self.Bind(wx.EVT_SIZE, self.OnSize)

        def OnSize(self, evt):
            hsize = evt.Size[0] * 0.75 # Constrain max height to 75% of width
            self.SetSizeHints(-1, hsize, maxH=hsize)
            evt.Skip()

Important part is here, you need to adjust the size hints on the sub panel window every time its size is being requested to change to tell the sizer to limit the constraints on the geometry of the window.

    class MainPanel(wx.Panel):   # main panel embedded in the main frame
        def __init__(self, parent):
            wx.Panel.__init__(self, parent, -1)
            self.mypanel = MyPanel(self)

            self.BackgroundColour = wx.BLACK

Background color set to help show difference between parent panel and its child panel which is colored red.

            vsizer = wx.BoxSizer(wx.VERTICAL)
            vsizer.AddStretchSpacer(0)
            vsizer.Add(self.mypanel, 1, wx.SHAPED|wx.EXPAND|wx.ALIGN_CENTER)
            vsizer.AddStretchSpacer(0)

            hsizer = wx.BoxSizer(wx.HORIZONTAL)
            hsizer.AddStretchSpacer(0)
            hsizer.Add(vsizer, 1, wx.EXPAND|wx.ALIGN_CENTER)
            hsizer.AddStretchSpacer(0)

            self.Sizer = hsizer;

Here in the MainPanel it uses two sizers with stretch spacers to keep the subpanel pushed towards the middle both horizontally and vertically as the window resizes.

    class MainFrame(wx.Frame):  # main frame window
        def __init__(self, parent, title):
            wx.Frame.__init__(self, parent, -1, title, size=(800,600))
            self.panel = MainPanel(self)
            self.Show()

    app = wx.App(0)
    frame = MainFrame(None, 'Test')
    app.MainLoop()

OTHER TIPS

You need to be using sizers for this type of thing, and if you are then using wx.SHAPED in the sizer.Add flags will maintain the aspect ratio as the size is changed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top