I was sitting Idle and I decided to write simple image viewer to try myself on DC/Canvas but I didn't find any tutorial to guide me as I have never done that before. Here there are some restriction and I cannot view showme do. So anyone to help me with basics how to draw image to a wxPanel?

Thanks!

Here is a very simple example ...

# show an image using a wx.PaintDC() canvas

import wx

class ImagePanel(wx.Panel):
    """ create a panel with a canvas to draw on"""
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, wx.ID_ANY)
        # pick a .jpg, .png, .gif, or .bmp image file you
        # have in the working folder or give full path
        image_file = 'Duck3.jpg'
        self.bmp = wx.Bitmap(image_file)

        # set up a paint event on a PaintDC canvas
        wx.EVT_PAINT(self, self.on_paint)

    def on_paint(self, event=None):
        # create the paint canvas
        self.dc = wx.PaintDC(self)
        # optionally clear the canvas
        self.dc.Clear()
        # draw the image with upper left corner at x=20, y=10
        self.dc.DrawBitmap(self.bmp, 20, 10, True)


app = wx.App(0)
frame = wx.Frame(None, wx.ID_ANY, size=(500, 400))
ImagePanel(frame)
frame.Show(True)
app.MainLoop()

Note:
Please remove self.dc.Clear() from the code to prevent flickering on frame resize. Sorry about that!

Edited 6 Years Ago by vegaseat: flicker

Attachments Duck3.jpg 5.97 KB

Here is a very simple example ...

Thanks Vega it works but it flickers and only stabilize while resizing to then flicker and flicker.... ad infinitum! What is the cause and how can I tame it?

BTW you didn't include that fat duck image :D

Edited 6 Years Ago by Stefano Mtangoo: n/a

Oh sorry! Please remove ...

# optionally clear the canvas
        self.dc.Clear()

... from the code!

Even after that, resizing the frame/canvas still screws with the event loop. So I would recommend fixing the frame size like this:

# show an image using a wx.PaintDC() canvas

import wx

class ImagePanel(wx.Panel):
    """ create a panel with a canvas to draw on"""
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, wx.ID_ANY)
        self.parent = parent
        # pick a .jpg, .png, .gif, or .bmp image file you
        # have in the working folder or give full path
        image_file = 'Duck3.jpg'
        self.bmp = wx.Bitmap(image_file)

        # set up a paint event on a PaintDC canvas
        wx.EVT_PAINT(self, self.on_paint)

    def on_paint(self, event=None):
        # create the paint canvas
        self.dc = wx.PaintDC(self)
        # draw the image with upper left corner at x=20, y=10
        self.dc.DrawBitmap(self.bmp, 20, 10, True)


app = wx.App(0)
frame = wx.Frame(None, wx.ID_ANY, size=(500, 400))
# optionally fix frame size to avoid resize problems
frame.SetMaxSize((500, 400))
frame.SetMinSize((500, 400))
ImagePanel(frame)
frame.Show(True)
app.MainLoop()

Edited 6 Years Ago by vegaseat: fix size

Even after that, resizing the frame/canvas still screws with the event loop. So I would recommend fixing the frame size like this:

Yes, it works! So what was wrong?

Yes, it works! So what was wrong?

You can avoid the panel and put the canvas on a frame to avoid some of the nasty flickering. For some odd reason Windows messes up the wx.EVT_PAINT event and keeps repainting, hence flickering.

One solution is to use a wx.ClientDC() canvas that does not need the wx.EVT_PAINT event ...

# show an image using a wx.ClientDC() canvas on a panel

import wx

class CanvasPanel(wx.Panel):
    """ create a panel with a canvas to draw on"""
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, wx.ID_ANY)
        # pick a .jpg, .png, .gif, or .bmp image file you
        # have in the working folder or give full path
        image_file = 'Duck3.jpg'
        self.bmp = wx.Bitmap(image_file)

        # this 50ms delay is needed to allow image loading first
        # may have to increase delay for very large images
        wx.FutureCall(50, self.make_canvas)
        # react to a resize event and redraw image
        wx.EVT_SIZE(self, self.make_canvas)

    def make_canvas(self, event=None):
        # create the paint canvas
        self.dc = wx.ClientDC(self)
        # draw the image with upper left corner at x=20, y=10
        self.dc.DrawBitmap(self.bmp, 20, 10, True)


app = wx.App(0)
frame = wx.Frame(None, wx.ID_ANY, size=(500, 400))
CanvasPanel(frame)
frame.Show(True)
app.MainLoop()

Edited 6 Years Ago by vegaseat: n/a

Your last post and the first one now makes alot of sense. I have read alot of wxDCs and they are very useful!
Thanks alot

This question has already been answered. Start a new discussion instead.