title: wx python image refresh on Windows
body: <p>I have an application that involves displaying multiple images. This works as I would expect on linux, but on Windows there is an annoying flash as the images are painted. This is best seen as a little square in the top left-hand corner of the screen where a flash of colour appears. Am I not approaching this requirement in the right way? Or is there some fix I should be applying to overcome the Windows effect? Or is it just my version on Windows (I only have one to test it: Windows 7 Ultimate)?</p>
  
  <p>I have tried Freeze and Thaw in <em>refresh_sizer_cell</em> but it didn't behave as I expected</p>
  
  <pre><code>import wx
  
  
  class ImageSizer(wx.Frame):
      BACKGROUND_COLOUR = (246, 244, 242)
      def __init__(self, parent, title):
          super(ImageSizer, self).__init__(parent, title=title)
  
          self.main_sizer = wx.GridBagSizer()
          self.SetSizer(self.main_sizer)
  
          cmd_reset = wx.Button(self, label='Reset')
          cmd_reset.Bind(wx.EVT_BUTTON, self.on_cmd_reset_click)
  
          cmd_cancel = wx.Button(self, label='Cancel')
          cmd_cancel.Bind(wx.EVT_BUTTON, self.on_cmd_cancel_click)
  
          self.main_sizer.Add((400, 0), pos=(0, 0), span=(1, 2))    # dummy to position Available
          self.main_sizer.Add((0, 100), pos=(1, 0), span=(1, 1))    # dummy to position Buttons
          self.main_sizer.Add(cmd_reset, pos=(2, 2), flag=wx.LEFT | wx.TOP, border=10)
          self.main_sizer.Add(cmd_cancel, pos=(2, 3), flag=wx.RIGHT | wx.BOTTOM | wx.TOP | wx.ALIGN_RIGHT, border=10)
  
          self.SetBackgroundColour(self.BACKGROUND_COLOUR)
          self.shape_types = {'available': 0, 'selected': 1}
          self.available_shapes = []
          self.selected_shapes = []
          self.initialise()
          self.Center()
          self.Fit()
          self.Show()
  
      def initialise(self):
          self.available_shapes = ['square', 'circle', 'triangle', 'cross']
          self.selected_shapes = []
          self.display_images()
  
      def display_images(self):
          available_sizer = ShapeSizer(self, self.available_shapes, self.shape_types['available'])
          self.refresh_sizer_cell(self.main_sizer, available_sizer, (1, 2), (1, 3))
          selected_sizer = ShapeSizer(self, self.selected_shapes, self.shape_types['selected'])
          self.refresh_sizer_cell(self.main_sizer, selected_sizer, (1, 1), (2, 1))
          self.Layout()
  
      @staticmethod
      def refresh_sizer_cell(sizer, item, pos, span, flag=wx.ALL, border=10):
          old_item = sizer.FindItemAtPosition(pos)
          if old_item is not None and old_item.IsWindow():
              old_item.GetWindow().Hide()
              sizer.Detach(old_item.GetWindow())
          sizer.Add(item, pos=pos, span=span, flag=flag, border=border)
  
      def on_available_shape_double_click(self, event):
          shape = event.GetEventObject().GetName()
          self.available_shapes.remove(shape)
          self.selected_shapes.append(shape)
          self.display_images()
  
      def on_selected_shape_double_click(self, event):
          shape = event.GetEventObject().GetName()
          self.selected_shapes.remove(shape)
          self.available_shapes.append(shape)
          self.display_images()
  
      def on_cmd_reset_click(self, event):
          self.initialise()
  
      def on_cmd_cancel_click(self, event):
          self.Destroy()
  
  
  class ShapeSizer(wx.Panel):
      def __init__(self, parent, shapes, shape_type):
          wx.Panel.__init__(self, parent, id = wx.ID_ANY)
  
          if shape_type == parent.shape_types['available']:
              size = 40
              action = parent.on_available_shape_double_click
          else:
              size = 80
              action = parent.on_selected_shape_double_click
          panel_sizer = wx.BoxSizer(wx.HORIZONTAL)
          shapes.sort()
          for shape in shapes:
              bitmap = wx.Bitmap(shape + '.png', wx.BITMAP_TYPE_PNG)
              bitmap = self.scale_bitmap(bitmap, size, size)
              img = wx.StaticBitmap(self, wx.ID_ANY, bitmap, name=shape)
              img.Bind(wx.EVT_LEFT_DCLICK, action)
              panel_sizer.Add(img, flag=wx.RIGHT, border=10)
          self.SetSizer(panel_sizer)
  
      @staticmethod
      def scale_bitmap(bitmap, width, height):
            image = wx.ImageFromBitmap(bitmap)
            image = image.Scale(width, height, wx.IMAGE_QUALITY_HIGH)
            result = wx.BitmapFromImage(image)
            return result
  
  if __name__  ==  '__main__':
          app = wx.App()
          ImageSizer(None, title='Image Sizer')
          app.MainLoop()
  </code></pre>
  
  <p>Here are the images:</p>
  
  <p><a href="https://i.stack.imgur.com/kT5zB.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/kT5zB.png" alt="circle.png"></a></p>
  
  <p><a href="https://i.stack.imgur.com/qP0om.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/qP0om.png" alt="cross.png"></a></p>
  
  <p><a href="https://i.stack.imgur.com/seRUd.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/seRUd.png" alt="square.png"></a></p>
  
  <p><a href="https://i.stack.imgur.com/W8mtX.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/W8mtX.png" alt="triangle.png"></a></p>