This is a repost of a question I posted on Stackoverflow.
I am trying to write an image control point selector function like MATLAB’s cpselect (http://www.mathworks.com/help/images/ref/cpselect.html) using wxPython. However, I have run into strange behavior that I do not understand. I have images inside a panel, and I would like the images to resize appropriately when the frame is resized. I call GetSize() on the frame, size the image equal to the panel size, and then update the wxBitmap. However, for some reason, the size return by GetSize is wrong the first time it is called. I have to set the bitmap and call it again to get the proper size. The following code is the smallest subset I could create to recreate the problem.
class Frame(wx.Frame):
def __init__(self, image, parent=None):
self.npimage = image # Components created with wxFowmBuilder
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, pos = wx.Point( -1,-1 ), size = wx.Size( -1,-1 ), style = wx.DEFAULT_FRAME_STYLE|wx.MAXIMIZE|wx.TAB_TRAVERSAL )
self.SetSizeHintsSz( wx.Size( 500,500 ), wx.Size( 1920,1000 ) )
bSizer = wx.BoxSizer( wx.VERTICAL )
self.bitmap = wx.StaticBitmap( self, wx.ID_ANY, wx.NullBitmap, wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer.Add( self.bitmap, 0, wx.ALL, 5 )
self.SetSizer( bSizer )
self.Layout()
bSizer.Fit( self )
self.Centre( wx.BOTH )
# Connect Events
#self.Bind( wx.EVT_SIZE, self.draw_image )
self.bitmap.Bind( wx.EVT_LEFT_DOWN, self.draw_image )
self.Maximize()
self.Refresh()
self.Update()
self.draw_image()
self.Refresh()
def draw_image(self, event=None):
# Determine how big the panel is so that we fill it with the image
panel_size = self.GetSize()
print panel_size
# Pull out this much from the original image
npimage = self.npimage[0:panel_size[1],0:panel_size[0],:]
# Turn numpy image into wxPython bitmaps
wximage = wx.EmptyImage(npimage.shape[1],npimage.shape[0])
wximage.SetData(npimage.tostring())
# Convert wxpython image to wxpython bitmap
wxbitmap = wximage.ConvertToBitmap()
self.bitmap.SetBitmap(bitmap=wxbitmap)
self.bitmap.Center()
# ----------------------------------------------------------------------------
def main():
# Generate random test images
image = asarray(np.random.rand(1000,1000,3)*255, dtype=np.uint8)
# Instantiate application (True/False for redirect output to stdout)
app = wx.App(True)
frame = Frame(image)
# Center frame on screen
frame.Center()
frame.Show(True) # True means the frame is visible
app.SetTopWindow(frame)
app.MainLoop()
if __name__ == '__main__':
main()
When you run it, draw_image is called, and the panel size output to stdout is wrong. If you left-click on the image, a wx.EVT_LEFT_DOWN event calls draw_image again, and this time the panel size is correct. Then, when you click again and draw_image is called for a third time, the image is finally how it should be. I am not sure what is going on or if I am missing some sort of update statement so that the image is correct from the first call.