wx.StaticBitmap cross-platform placement issue

Hello,

Because I'm currently building a simple cross platform Python GUI
application, I decided to use wxPython. All went fine until I ran in
the following issue.

I have a wx.Frame, with a certain image on it (wx.StaticBitmap). This
image needs to 'start' on (0,0), the left upper corner of the
wx.Frame. In short, this became the code below [2], using the image
[3]. Strangely this code is behaving differently on Windows and
Linux.

On Linux, this code behaves as expected. The (small) image is placed
on the left upper corner. It looks like this:
http://med.hro.nl/vlikb/wxpython/bitmap_placement_linux.png

On Windows, however, the resulting frame is different. The image is
placed in the center of the frame, as can be seen here:
http://med.hro.nl/vlikb/wxpython/bitmap_placement_windows.png

In my understanding, the image should be in the upper left corner as
well. Does anyone know how this can happen? And how this can be fixed?
The images need to 'start' at (0,0), even on Windows.

A minimal testcase can be found at [1].

Regards,

Kevin van der Vlist

[1]: http://med.hro.nl/vlikb/wxpython/
[2]: http://med.hro.nl/vlikb/wxpython/bitmap_placement.png
[3]: Proof of concept
import wx

class Frame(wx.Frame):
    def __init__(self):

        title="bitmap placement issue"
        pos=(0, 0)
        size=(320, 240)

        wx.Frame.__init__(self, parent=None, title=title, pos=pos,
size=size)

        bm = wx.BitmapFromImage(wx.Image("bitmap_placement.png",
wx.BITMAP_TYPE_PNG))

        self.bitmap = wx.StaticBitmap(parent=self, pos=pos, bitmap=bm,
size=size)

class App(wx.App):
    def OnInit(self):
        self.frame = Frame()
        self.frame.Show()
        return True

if __name__ == '__main__':
    app = App()
    app.MainLoop()

Kevin van der Vlist wrote:

I have a wx.Frame, with a certain image on it (wx.StaticBitmap). This
image needs to 'start' on (0,0), the left upper corner of the
wx.Frame. In short, this became the code below [2], using the image
[3]. Strangely this code is behaving differently on Windows and
Linux.
...
On Windows, however, the resulting frame is different. The image is
placed in the center of the frame, as can be seen here:
Login Hogeschool Rotterdam

In my understanding, the image should be in the upper left corner as
well. Does anyone know how this can happen? And how this can be fixed?
The images need to 'start' at (0,0), even on Windows.

It's complicated. Isn't it always?

When a frame contains a single child, wx by default expands that child
to fill the frame. In your case, the static bitmap code is expanded to
fill the wx.Frame, despite your "size" specification, and despite the
size of the incoming image. The static bitmap is one of those rather
primitive wrappers around native controls. In Windows, the native
static bitmap control centers its bitmap within its container. Hence,
the behavior you see. The Linux native static bitmap control must have
different rules.

In general, it's not a good idea to add controls directly to a frame, in
part because of side effects like this. The solution is to add a panel
to your frame, and add the StaticBitmap to the panel, and set the size
of the StaticBitmap to the actual size of the bitmap.

import wx

class Frame(wx.Frame):
    def __init__(self):
        title="bitmap placement issue"
        pos=(0, 0)
        size=(800, 600)
        wx.Frame.__init__(self, parent=None, title=title, pos=pos,
size=size)
        p = wx.Panel(self)
        bm = wx.BitmapFromImage(wx.Image("bitmap_placement.png",
wx.BITMAP_TYPE_PNG))
        self.bitmap = wx.StaticBitmap(parent=p, pos=pos, bitmap=bm,
size=bm.Size)

class App(wx.App):
    def OnInit(self):
        self.frame = Frame()
        self.frame.Show()
        return True

if __name__ == '__main__':
    app = App(0)
    app.MainLoop()

···

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

Hello,

Because I'm currently building a simple cross platform Python GUI
application, I decided to use wxPython. All went fine until I ran in
the following issue.

I have a wx.Frame, with a certain image on it (wx.StaticBitmap). This
image needs to 'start' on (0,0), the left upper corner of the
wx.Frame. In short, this became the code below [2], using the image
[3]. Strangely this code is behaving differently on Windows and
Linux.

On Linux, this code behaves as expected. The (small) image is placed
on the left upper corner. It looks like this:
Login Hogeschool Rotterdam

On Windows, however, the resulting frame is different. The image is
placed in the center of the frame, as can be seen here:
Login Hogeschool Rotterdam

In my understanding, the image should be in the upper left corner as
well. Does anyone know how this can happen?

Actually the static bitmap widget is being resized to fill the whole frame on both platforms, (this is a feature of wxFrame, that if it has only one child then that child is moved/sized such that it fills the frame's client area.) The widgets just have different behaviors when the widget is larger than the image.

And how this can be fixed?
The images need to 'start' at (0,0), even on Windows.

You can override the frame's default one child behavior by using a sizer instead of absolute positioning and sizing. Or you can use a panel as the only child of the frame and then make that panel be the parent of the static bitmap widget. It would still be a good idea to use a sizer on the panel, but absolute positioning/sizing would work too.

···

On 3/6/12 2:19 AM, Kevin van der Vlist wrote:

--
Robin Dunn
Software Craftsman

Hello,

Because I’m currently building a simple cross platform Python GUI
application, I decided to use wxPython. All went fine until I ran in
the following issue.

I have a wx.Frame, with a certain image on it (wx.StaticBitmap). This
image needs to ‘start’ on (0,0), the left upper corner of the
wx.Frame. In short, this became the code below [2], using the image
[3]. Strangely this code is behaving differently on Windows and
Linux.

On Linux, this code behaves as expected. The (small) image is placed
on the left upper corner. It looks like this:
http://med.hro.nl/vlikb/wxpython/bitmap_placement_linux.png

On Windows, however, the resulting frame is different. The image is
placed in the center of the frame, as can be seen here:
http://med.hro.nl/vlikb/wxpython/bitmap_placement_windows.png

In my understanding, the image should be in the upper left corner as
well. Does anyone know how this can happen?
Actually the static bitmap widget is being resized to fill the whole
frame on both platforms, (this is a feature of wxFrame, that if it has
only one child then that child is moved/sized such that it fills the
frame’s client area.) The widgets just have different behaviors when
the widget is larger than the image.

Thanks for the explanation Tim, Robin. Now I know why this behavior manifested itself. It’s clear now.

I ended up using a single panel, on which the bitmap is displayed, just as the demo Tim provided. Because of the really small usecase this program is needed for, this is enough.

Thanks for the help.

Regards,

Kevin

···

On Tuesday, March 6, 2012 7:29:22 PM UTC+1, Robin Dunn wrote:

On 3/6/12 2:19 AM, Kevin van der Vlist wrote:

And how this can be fixed?
The images need to ‘start’ at (0,0), even on Windows.

You can override the frame’s default one child behavior by using a sizer
instead of absolute positioning and sizing. Or you can use a panel as
the only child of the frame and then make that panel be the parent of
the static bitmap widget. It would still be a good idea to use a sizer
on the panel, but absolute positioning/sizing would work too.


Robin Dunn
Software Craftsman
http://wxPython.org