ρss
ρss

Reputation: 5315

Changing the image size dynamically when the sizer's size changes in wxPython

I am working with python v2.7 and wxPython v3.0 on Windows 8 OS. In the code snippet provided below simply creates a frame which has a vertical sizer that contains an image and an other horizontal sizer that in turn contains two panels.

Question: When I resize the frame by dragging the border, the panels resize automatically. Unlike the panels the image doesn't resize? How can I make my image to behave like panels for the case of resizing?

Code: The image file used can be downloaded from here: green.bmp

import wx

class Frame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, style=wx.DEFAULT_FRAME_STYLE)
        panelA = wx.Panel(self,-1)
        imageFile = wx.Image('greenbig.bmp', wx.BITMAP_TYPE_ANY).ConvertToBitmap()
        myBitmap = wx.StaticBitmap(panelA, -1, imageFile)

        panel1 = wx.Panel(self, -1,style=wx.SIMPLE_BORDER)
        panel2 = wx.Panel(self, -1, style=wx.SIMPLE_BORDER)
        panelSizer = wx.BoxSizer(wx.HORIZONTAL)
        panelSizer.Add(panel1, 1, wx.ALL|wx.EXPAND, 0)
        panelSizer.Add(panel2, 1, wx.ALL|wx.EXPAND, 0)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(panelA, 1, wx.ALL|wx.EXPAND, 0)
        sizer.Add(panelSizer,  1, wx.ALL|wx.EXPAND, 0)
        self.SetSizer(sizer)

        self.Show(True)

app = wx.App()
frame = Frame(None, wx.ID_ANY, 'Image')
app.MainLoop()

Thank you for your time!

Upvotes: 2

Views: 466

Answers (2)

John
John

Reputation: 1819

(eight years later) I was struggling to show an image that was dynamically resized with the window frame. These days, I'm using Python 3 with wxPython version 4. I pieced this solution from a lot of reading of the documentation and tips on how best to use sizers. I then whittled my code down to the absolute minimum required to accomplish this narrow use case.

Notice that I don't ever call Frame.Layout() or Panel.Layout() because I rely on the initial size of the Frame and the fact that a single Panel in a Frame will be automatically resized with the Frame. Also, any call to Fit() was unnecessary. The sizer containing the ImagePanel does need the EXPAND flag, but the ImagePanel does not need a sizer itself.

Note: you'll have to supply your own example image to load.

import wx


class ImagePanel(wx.Panel):
    def __init__(self, parent):
        super().__init__(parent)
        self.img = wx.Image(width=1, height=1)
        self.ctrl = wx.StaticBitmap(self, bitmap=self.img.ConvertToBitmap())
        self.Bind(wx.EVT_SIZE, self.on_resize)

    def load_image(self):
        with open('image.png', 'rb') as fin:
            self.img = wx.Image(fin)
        self.update_bitmap()

    def update_bitmap(self):
        w, h = self.GetSize()
        self.ctrl.SetBitmap(self.img.Scale(w, h).ConvertToBitmap())

    def on_resize(self, evt):
        self.update_bitmap()


class MainWindow(wx.Frame):
    def __init__(self):
        initial_size = wx.Size(width=480, height=480)
        super().__init__(None, wx.ID_ANY, title='Main Window Title', size=initial_size)
        self.panel = wx.Panel(self)
        self.image = ImagePanel(self.panel)

        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox.Add(self.image, proportion=1, flag=wx.EXPAND)
        self.panel.SetSizer(vbox)


if __name__ == '__main__':
    app = wx.App()
    win = MainWindow()
    win.Show()
    win.image.load_image()
    app.MainLoop()

Upvotes: 1

VZ.
VZ.

Reputation: 22753

The image will never be resized automatically. If you want this behaviour, you need to handle wxEVT_SIZE and do it yourself in its handler.

Upvotes: 0

Related Questions