How to remove image in wxPython

别说谁变了你拦得住时间么 提交于 2019-12-13 10:29:19

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!