我正在尝试删除放置在面板上某个随机点的图像。此解决方案有效,但它取决于我使用的配色方案。有没有更好的方法呢?
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()
[12月17日编辑:将wx.PaintDC改为wx.ClientDC]
答案 0 :(得分:0)
您只需要Refresh
Panel
而无需重新绘制位图。您将在图片的位置获得Panel
背景样式。这适用于您当前的代码(固定大小Panel
),但不适用于可以调整大小的Frame
,因为这会产生EVT_PAINT
并且您将再次绘制您的位图。要解决此问题,您可以使用标志来判断何时需要Refresh
而不使用位图。
代码示例可以是:
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
另一种选择是创建一个大小为0的Bitmap
来替换原来的_on_paint
。请注意,为此,您必须将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()
调用与位图的读取分离。否则,每次调整窗口大小时,您都会重新阅读原始图片:
{{1}}