Lets say I have a wxBitmapButton
and a text label wxButton
in the same horizontal wxBoxSizer
. The bitmap assigned to the wxBitmapButton
is too big for the button (and stretches it larger).
I want the bitmap to be downscaled so that it fits the button exactly, no longer stretching the button size, while the button itself is no smaller than the "standard" button size.
I want this downscaling to happen automatically and dynamically. How can I accomplish this?
I'm using macOS Catalina 10.15.4, Python 3.8.2, and wxPython 4.1.0a1 from the snapshots folder. I have a normal DPI monitor (although I'd want my code to run on both high-DPI and normal monitors).
Minimal example:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from base64 import b64decode
from wx import *
class TestFrame(Frame):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._sizer = BoxSizer(HORIZONTAL)
button1 = BitmapButton(self) # I want button1 to be the same size as the other buttons in the sizer, and for the bitmap to downscale to fit
data = b64decode(''.join([ # 64x64 px PNG
'iVBORw0KGgoAAAANSUhEUgAAAEAAAABA',
'CAMAAACdt4HsAAAANlBMVEUAAAAAAAAA',
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC3',
'dmhyAAAAEXRSTlMArNkZmwdF04UT9+zS',
'pndhKrYPNwAAAABsSURBVFjD7ZZJCoAw',
'EAQ1Olnc5/+fVfAaJFAHCXTdqyCZSw9C',
'9IDFaMQvyT1NIJD9IYDC7rBwOi3MKqig',
'wh+FksdvwltYr7pvmzeyWDUQvZkDB/AT',
'6CfSM8qXLx/4cOLQkUVnHh2aeOoK0QE3',
'Edkb36fiI5sAAAAASUVORK5CYII='
]))
bmp = Bitmap.NewFromPNGData(data, len(data))
button1.SetBitmap(bmp)
# If uncommented, this bit of code will simulate the effect I want
# img = bmp.ConvertToImage()
# scaled = img.Scale(17, 17, IMAGE_QUALITY_HIGH)
# button1.SetBitmap(scaled.ConvertToBitmap())
button2 = Button(self, label='MyButton')
button3 = Button(self, label='MyButton')
button4 = Button(self, label='MyButton')
self._sizer.Add(button1, 0, ALL, 5)
self._sizer.Add(button2, 0, ALL, 5)
self._sizer.Add(button3, 0, ALL, 5)
self._sizer.Add(button4, 0, ALL, 5)
self.SetSizer(self._sizer)
def main():
app = App()
frm = TestFrame(None)
frm.Show()
app.MainLoop()
if __name__ == '__main__':
main()
wxButton
won't do image scaling for you, you need to resize the bitmap yourself. This is not terribly difficult, as you can just use wxImage::Size()
or wxImage::Resize()
for this, but it might give non-ideal results for small images with straight lines like the ones you use, which is why it's usually better to have a few pre-rendered bitmaps and choose the most suitable among them instead.
In any case, you still need to know the size to use. It should normally be returned by wxArtProvider::GetSizeHint(), although I admit that I'm not sure if it works correctly when using non-default DPI under macOS (but if it doesn't, it should be reported as a bug and fixed).