问题
I am trying to remove an image that has been placed at some random point on a panel. This solution works but it is dependent upon the colour scheme that I am using. Is there a better way of doing this?
import wx
from PIL import Image
import random
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "Remove image")
panel = MainPanel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(panel)
self.SetSizerAndFit(sizer)
self.Centre()
self.Show()
class MainPanel(wx.Panel):
"""Create a panel class to contain screen widgets."""
def __init__(self, frame):
wx.Panel.__init__(self, frame)
self.Bind(wx.EVT_PAINT, self._on_paint)
cmd_refresh = wx.Button(self, wx.ID_REFRESH)
cmd_refresh.Bind(wx.EVT_BUTTON, self._on_cmd_refresh_click)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add((500, 300))
sizer.Add(cmd_refresh, flag=wx.ALL|wx.ALIGN_CENTER, border=10)
self.SetSizer(sizer)
self.x_pos = random.randint(0, 100)
self.y_pos = random.randint(0, 100)
def _on_paint(self, event):
bitmap = self._get_image()
self._draw_image(bitmap)
def _get_image(self):
bitmap = wx.Bitmap()
bitmap.LoadFile("red.png", wx.BITMAP_TYPE_ANY)
self.image_width = bitmap.GetWidth()
self.image_height = bitmap.GetHeight()
return bitmap
def _draw_image(self, bitmap):
dc = wx.ClientDC(self)
dc.DrawBitmap(bitmap, self.x_pos, self.y_pos, True)
def _on_cmd_refresh_click(self, event):
del event
colour = (212, 212, 212)
blank_image = Image.new('RGB', (self.image_width, self.image_height), colour)
bitmap = wx.Bitmap.FromBuffer(self.image_width, self.image_height, blank_image.tobytes())
self._draw_image(bitmap)
if __name__ == '__main__':
screen_app = wx.App()
main_frame = MainFrame()
screen_app.MainLoop()
[EDIT 29 Dec 17: change wx.PaintDC to wx.ClientDC]
回答1:
You only need to Refresh
your Panel
without redrawing the bitmap. You will get your Panel
background style in the place of the picture. This would work for your current code (fixed-size Panel
) but not for a Frame
that could be resized because this would produce and EVT_PAINT
and you will have again your bitmap drawn. To solve this, you can use a flag to tell when you want a Refresh
without bitmap.
Example of code could be:
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "Remove image")
panel = MainPanel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(panel, 1, wx.EXPAND) # I made the panel expandable sizable
self.SetSizerAndFit(sizer)
self.Centre()
self.Show()
class MainPanel(wx.Panel):
"""Create a panel class to contain screen widgets."""
def __init__(self, frame):
wx.Panel.__init__(self, frame)
self.Bind(wx.EVT_PAINT, self._on_paint)
cmd_refresh = wx.Button(self, wx.ID_REFRESH)
cmd_refresh.Bind(wx.EVT_BUTTON, self._on_cmd_refresh_click)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add((500, 300))
sizer.Add(cmd_refresh, flag=wx.ALL|wx.ALIGN_CENTER, border=10)
self.SetSizer(sizer)
self.x_pos = random.randint(0, 100)
self.y_pos = random.randint(0, 100)
self.refresh = False # flag to control drawing of bitmap
def _on_paint(self, event):
if self.refresh: return # for a clean background, return
bitmap = self._get_image()
self._draw_image(bitmap)
def _get_image(self):
bitmap = wx.Bitmap()
bitmap.LoadFile("mypng.PNG", wx.BITMAP_TYPE_ANY)
return bitmap
def _draw_image(self, bitmap):
dc = wx.ClientDC(self)
dc.DrawBitmap(bitmap, self.x_pos, self.y_pos, True)
def _on_cmd_refresh_click(self, event):
self.refresh = True # forget the bitmap
self.Refresh() # and refresh the screen
Another option is to create a Bitmap
of size 0 to replace the original one. Note that for this you have to decouple the _on_paint
call from the reading of the bitmap. Otherwise you will re-read the original picture each time you resize your window:
class MainPanel(wx.Panel):
"""Create a panel class to contain screen widgets."""
def __init__(self, frame):
wx.Panel.__init__(self, frame)
self.Bind(wx.EVT_PAINT, self._on_paint)
cmd_refresh = wx.Button(self, wx.ID_REFRESH)
cmd_refresh.Bind(wx.EVT_BUTTON, self._on_cmd_refresh_click)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add((500, 300))
sizer.Add(cmd_refresh, flag=wx.ALL|wx.ALIGN_CENTER, border=10)
self.SetSizer(sizer)
self.x_pos = random.randint(0, 100)
self.y_pos = random.randint(0, 100)
self._get_image()
def _on_paint(self, event):
self._draw_image()
def _get_image(self):
self.bitmap = wx.Bitmap()
self.bitmap.LoadFile("mypng.PNG", wx.BITMAP_TYPE_ANY)
def _draw_image(self):
dc = wx.ClientDC(self)
dc.DrawBitmap(self.bitmap, self.x_pos, self.y_pos, True)
def _on_cmd_refresh_click(self, event):
self.bitmap = wx.Bitmap(0,0)
self._draw_image()
self.Refresh()
来源:https://stackoverflow.com/questions/47203589/how-to-remove-image-in-wxpython