Objective
StaticBitmap
that can be updated by main frame's method and has scrolls.
Details
I want to add an image (StaticBitmap
) in the first cell of the sizer. The issue is that the image is cropped and has no scrolls.
The image can not be scaled to fit in the cell. This is not what I need for my program.
Uploaded code shows my last attempt to make it work. I tried to wrap the StaticBitmap
in ScrolledPanel
. This works until I update the Bitmap (function update_crnt_bm
) and then resize the frame.
Code
from PIL import Image
import wx
import wx.lib.scrolledpanel as scrl
class Button(wx.Button):
def __init__(self, parent, label, action=None):
super().__init__(parent, label=label)
self.Bind(wx.EVT_BUTTON, action)
class ImgPanel(scrl.ScrolledPanel):
'''Scrolled Panel with Image'''
def __init__(self, parent, bitmap):
super().__init__(parent)
self.img_sizer = wx.BoxSizer(wx.VERTICAL)
self.sbm = wx.StaticBitmap(self, bitmap=bitmap)
self.img_sizer.Add(self.sbm, 1, wx.EXPAND)
self.SetSizer(self.img_sizer)
self.SetupScrolling()
self.Bind(wx.EVT_SIZE, self.on_resize)
def load_bm(self, bitmap):
self.sbm.Destroy()
self.sbm = wx.StaticBitmap(self, bitmap=bitmap)
def on_resize(self, event):
super().Layout()
class MainFrame(wx.Frame):
def __init__(self, fns):
super().__init__(None, title='Test multiple images')
self.resized = False
if len(fns) < 1:
print('Please select at lease one image')
exit(1)
self.fns = fns
self.init_panel()
self.Show()
def side_bar(self):
sizer = wx.GridBagSizer()
for i, fn in enumerate(self.fns):
bttn = Button(self.panel, 'Image #'+str(i), self.getupd_crnt_bm(fn))
sizer.Add(bttn, pos=(i,0))
return sizer
def init_panel(self):
self.panel = wx.Panel(self)
self.sizer = wx.GridBagSizer()
self.sizer.Add(self.side_bar(), pos=(0,1))
self.img_panel = ImgPanel(self.panel, self.open_bm(self.fns[0]))
self.sizer.Add(self.img_panel, pos=(0,0), flag=wx.EXPAND)
self.sizer.AddGrowableCol(0)
self.sizer.AddGrowableRow(0)
self.panel.SetSizerAndFit(self.sizer)
def getupd_crnt_bm(self, fn):
def update_crnt_bm(event):
bm = self.img_to_bm(Image.open(fn))
self.img_panel.load_bm(bm)
self.current_bm = bm
return update_crnt_bm
def open_bm(self, fn):
return self.img_to_bm(Image.open(fn))
def img_to_bm(self, image):
scale = 0.3
image = image.resize((int(image.size[0]*scale), int(image.size[1]*scale)))
width, height = image.size
bm = wx.Bitmap.FromBuffer(width, height, image.tobytes())
return bm
if __name__ == '__main__':
fns = ['image0.jpg', 'image1.jpg', 'image2.jpg']
app = wx.App()
frame = MainFrame(fns)
app.MainLoop()
Versions
- Python 3.6.5
- wx 4.0.1 msw (phoenix)
- PIL 1.1.7
Answer to my own question
Leaving it here anyway so others can find this code.
Solution
It turns out that re-created
StaticBitmap
had to be added to a sizer once again. This is theload_bm
function now. (Can't believe it was so obvious)Additionally, the scroll status is set to 0. This forces the image to be added in upper-left corner of
ScrolledPanel
.