Reputation: 422
I'm building a software where I need to display buttons over a image and make it stay somewhat in the same position (the best as possible) when the sizer the image is in gets resized.
The button-display-on-image is already done. I just need to get the math working now. I've tried a bunch of stuff with no luck yet. I guess the magic need to happen in the updateButtons function.
Thanks!
import wx
import wx.lib.platebtn as pb
class MainFrame(wx.Frame):
def __init__(self, parent):
super().__init__(parent)
self.bInfoSizerVisibility = False
self.images = []
self.initUI()
self.CenterOnScreen()
self.Bind(wx.EVT_SIZE, self.OnResizing)
def initUI(self):
self.imageSizer = wx.BoxSizer(wx.VERTICAL)
self.imageSizer.SetMinSize((800, 600))
self.bitmap = None
self.image = None
self.aspect = None
self.bmpImage = wx.StaticBitmap(self, wx.ID_ANY)
self.imageSizer.Add(self.bmpImage, 1, wx.EXPAND)
self.btn = pb.PlateButton(self.bmpImage, -1, 'Click Me!', style=pb.PB_STYLE_NOBG)
self.btn.Bind(wx.EVT_BUTTON, self.test)
self.btn.Position = 250, 250
self.SetSizerAndFit(self.imageSizer)
self.frameImage()
def test(self, event):
print('Button Pressed!')
def updateButtons(self):
w, h = self.bmpImage.GetSize()
u, v = 0.3, 0.7
self.btn.Position = int(u * w), int(v * h)
def frameImage(self, isJustResize=False):
if not isJustResize:
self.bitmap = wx.Bitmap('image.jpg', wx.BITMAP_TYPE_ANY)
self.image = wx.Bitmap.ConvertToImage(self.bitmap)
self.aspect = self.image.GetSize()[1] / self.image.GetSize()[0]
self.Layout()
sW, sH = self.imageSizer.GetSize()
newW = sW
newH = int(newW * self.aspect)
if newH > sH:
newH = sH
newW = int(newH / self.aspect)
image = self.image.Scale(newW, newH)
self.bmpImage.SetBitmap(image.ConvertToBitmap())
self.Layout()
self.Refresh()
self.updateButtons()
# print(f"Image New Size: ({newW}, {newH})")
# print(f"App Size: {self.GetSize()}")
# print(f"imageSizer Size: {self.imageSizer.GetSize()}\n")
def OnResizing(self, event):
self.frameImage(True)
event.Skip()
app = wx.App()
frame = MainFrame(None)
frame.Show()
app.MainLoop()
Upvotes: 0
Views: 36
Reputation: 3699
You need to take into account the fact that as you resize the image, white space appears, either to the left and right, or on top and bottom. Remember, the button position is relative to the frame and not the image.
I have rewritten your updateButtons method to implement this.
I have assumed that your button's position will be 0.3 * the width of the image from the left and 0.7 * the height of the image from the top
import wx
import wx.lib.platebtn as pb
IMAGE_MINIMUM_SIZE = (800, 600)
BUTTON_POSITION_RATIO = (0.3, 0.7)
class MainFrame(wx.Frame):
def __init__(self, parent):
super().__init__(parent)
self.bInfoSizerVisibility = False
self.images = []
self.initUI()
self.CenterOnScreen()
self.Bind(wx.EVT_SIZE, self.OnResizing)
def initUI(self):
self.imageSizer = wx.BoxSizer(wx.VERTICAL)
self.imageSizer.SetMinSize(IMAGE_MINIMUM_SIZE)
self.bitmap = None
self.image = None
self.image_aspect = None
self.bmpImage = wx.StaticBitmap(self, wx.ID_ANY)
self.imageSizer.Add(self.bmpImage, 1, wx.EXPAND)
self.btn = pb.PlateButton(self, -1, 'Click Me!', style=pb.PB_STYLE_NOBG)
self.btn.Bind(wx.EVT_BUTTON, self.test)
self.SetSizerAndFit(self.imageSizer)
self.frameImage()
def test(self, event):
print('Button Pressed!')
def updateButtons(self):
frame_aspect = self.Size[0] / self.Size[1]
button_horizontal = int(self.Size[0] * BUTTON_POSITION_RATIO[0])
button_vertical = int(self.Size[1] * BUTTON_POSITION_RATIO[1])
if self.image_aspect <= frame_aspect:
# Frame is wider than image so find the horizontal white space size to add
image_width = self.Size[1] * self.image_aspect
horizontal_offset = (self.Size[0] - image_width)/2
button_horizontal = int(horizontal_offset + image_width * BUTTON_POSITION_RATIO[0])
elif self.image_aspect > frame_aspect:
# Frame is higher than image so find the vertical white space size to add
image_height = self.Size[0] / self.image_aspect
vertical_offset = (self.Size[1] - image_height)/2
button_vertical = int(vertical_offset + image_height * BUTTON_POSITION_RATIO[1])
self.btn.Position = (button_horizontal, button_vertical)
def frameImage(self, isJustResize=False):
if not isJustResize:
self.bitmap = wx.Bitmap('image.jpg', wx.BITMAP_TYPE_ANY)
self.image = wx.Bitmap.ConvertToImage(self.bitmap)
self.image_aspect = self.image.GetSize()[0] / self.image.GetSize()[1]
image_width, image_height = self.imageSizer.GetSize()
new_image_width = image_width
new_image_height = int(new_image_width / self.image_aspect)
if new_image_height > image_height:
new_image_height = image_height
new_image_width = int(new_image_height * self.image_aspect)
image = self.image.Scale(new_image_width, new_image_height)
self.bmpImage.SetBitmap(image.ConvertToBitmap())
self.Layout()
self.Refresh()
self.updateButtons()
def OnResizing(self, event):
self.frameImage(True)
event.Skip()
app = wx.App()
frame = MainFrame(None)
frame.Show()
app.MainLoop()
Upvotes: 1