Using wx.EVT_PAINT and wx.PaintDC

Hi,

You use wx.EVT_PAINT and wx.PaintDC to draw shapes, so that when window is resized (redrawn) shapes do not appear. This works when the window is created. But, how will I preserve the shapes that I create after window is created?

Below, I present you a code, when the app first starts, a rectangle is drawn on the window. When user clicks somewhere on the window, another rectangle is created. The initial rectangle is always preserved because it is bind to wx.EVT_PAINT event, so that it will be redrawn every time the window is redrawn.

But the second rectangle is not associated to the wx.EVT_PAINT, therefore it is lost when window is redrawn. How do I preserve the second rectangle as well?

import wx

class MyPanel(wx.Panel):
def init(self, parent):
wx.Panel.init(self, parent, -1)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_LEFT_DCLICK, self.on_left_double_click)

def OnPaint(self, evt):
    dc = wx.PaintDC(self)
    dc.DrawRectangle(50, 60, 90, 40)

def on_left_double_click(self, evt):
    x = evt.GetX()
    y = evt.GetY()
    dc = wx.ClientDC(self)
    dc.SetBrush(wx.Brush("yellow"))
    dc.DrawRectangle(x, y, 90, 40)

class MyForm(wx.Frame):

def __init__(self):
    wx.Frame.__init__(self, None, wx.ID_ANY, "Test",style=wx.DEFAULT_FRAME_STYLE,size=wx.Size(400, 300))
    self.main_panel = MyPanel(self)

if name == “main”:
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()

CORRECTION:

Above I said:

“You use wx.EVT_PAINT and wx.PaintDC to draw shapes, so that when window is resized (redrawn) shapes do not appear”

What I really wanted to say was:

“You use wx.EVT_PAINT and wx.PaintDC to draw shapes, so that when window is resized (redrawn) shapes are not lost”

···

On Monday, January 18, 2016 at 3:08:22 PM UTC+2, steve wrote:

Hi,

You use wx.EVT_PAINT and wx.PaintDC to draw shapes, so that when window is resized (redrawn) shapes do not appear. This works when the window is created. But, how will I preserve the shapes that I create after window is created?

Below, I present you a code, when the app first starts, a rectangle is drawn on the window. When user clicks somewhere on the window, another rectangle is created. The initial rectangle is always preserved because it is bind to wx.EVT_PAINT event, so that it will be redrawn every time the window is redrawn.

But the second rectangle is not associated to the wx.EVT_PAINT, therefore it is lost when window is redrawn. How do I preserve the second rectangle as well?

import wx

class MyPanel(wx.Panel):
def init(self, parent):
wx.Panel.init(self, parent, -1)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_LEFT_DCLICK, self.on_left_double_click)

def OnPaint(self, evt):
    dc = wx.PaintDC(self)
    dc.DrawRectangle(50, 60, 90, 40)
def on_left_double_click(self, evt):
    x = evt.GetX()
    y = evt.GetY()
    dc = wx.ClientDC(self)
    dc.SetBrush(wx.Brush("yellow"))
    dc.DrawRectangle(x, y, 90, 40)

class MyForm(wx.Frame):

def __init__(self):
    wx.Frame.__init__(self, None, wx.ID_ANY, "Test",style=wx.DEFAULT_FRAME_STYLE,size=wx.Size(400, 300))
    self.main_panel = MyPanel(self)

if name == “main”:
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()

the idea here is the you draw EVERYTHING in a paint event.

When you add more stuff to draw, you need to store it somehwere, so it can be re-drawn.

See enclosed for (one) solution.

You also might want to take a look at wx.lib.floatcanvas – it handles all this for you, along with zooming, panning, etc…

wx_paint.py (908 Bytes)

···

On Mon, Jan 18, 2016 at 5:08 AM, steve oslocourse@gmail.com wrote:

Hi,

You use wx.EVT_PAINT and wx.PaintDC to draw shapes, so that when window is resized (redrawn) shapes do not appear. This works when the window is created. But, how will I preserve the shapes that I create after window is created?

Below, I present you a code, when the app first starts, a rectangle is drawn on the window. When user clicks somewhere on the window, another rectangle is created. The initial rectangle is always preserved because it is bind to wx.EVT_PAINT event, so that it will be redrawn every time the window is redrawn.

But the second rectangle is not associated to the wx.EVT_PAINT, therefore it is lost when window is redrawn. How do I preserve the second rectangle as well?

import wx

class MyPanel(wx.Panel):
def init(self, parent):
wx.Panel.init(self, parent, -1)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_LEFT_DCLICK, self.on_left_double_click)

def OnPaint(self, evt):
    dc = wx.PaintDC(self)
    dc.DrawRectangle(50, 60, 90, 40)
def on_left_double_click(self, evt):
    x = evt.GetX()
    y = evt.GetY()
    dc = wx.ClientDC(self)
    dc.SetBrush(wx.Brush("yellow"))
    dc.DrawRectangle(x, y, 90, 40)

class MyForm(wx.Frame):

def __init__(self):
    wx.Frame.__init__(self, None, wx.ID_ANY, "Test",style=wx.DEFAULT_FRAME_STYLE,size=wx.Size(400, 300))
    self.main_panel = MyPanel(self)

if name == “main”:
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()

You received this message because you are subscribed to the Google Groups “wxPython-users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

You also might want to take a look at wx.lib.floatcanvas -- it handles all

this for you, along with zooming, panning, etc...

OK, since I brought it up -- here is a similar example with floatcanvas.

Wow! I really need to modernize that code!

note that it doesn't use pixel coordinates, and by default x is up rather
than down, so a little different -- but you get paning and zooming, etc.

The best place to look for examples in in the source:

http://svn.wxwidgets.org/viewvc/wx/wxPython/3rdParty/FloatCanvas/Demos/

-Chris

floatcanvas_example.py (2.1 KB)

···

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Hi Chris,

Thank you for the help,

In your first example, it uses Refresh() method to send a EVT_PAINT event, but it causes the drawing area to flash (everything first disappears then reappears), and it doesn’t look good. Isn’t there a better way?

Best regards

I’ve run into this in the past and have used one of the following to fix it:
self.SetDoubleBuffered(True)

wx.CallAfter()

···

On Tue, Jan 19, 2016 at 1:16 PM, steve oslocourse@gmail.com wrote:

Hi Chris,

Thank you for the help,

In your first example, it uses Refresh() method to send a EVT_PAINT event, but it causes the drawing area to flash (everything first disappears then reappears), and it doesn’t look good. Isn’t there a better way?

Best regards

You received this message because you are subscribed to the Google Groups “wxPython-users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Hi john,

How would you use those statements in Steve’s example?

···

On Wednesday, January 20, 2016 at 7:26:49 PM UTC+2, johnf wrote:

I’ve run into this in the past and have used one of the following to fix it:
self.SetDoubleBuffered(True)

wx.CallAfter()

On Tue, Jan 19, 2016 at 1:16 PM, steve osloc...@gmail.com wrote:

Hi Chris,

Thank you for the help,

In your first example, it uses Refresh() method to send a EVT_PAINT event, but it causes the drawing area to flash (everything first disappears then reappears), and it doesn’t look good. Isn’t there a better way?

Best regards

You received this message because you are subscribed to the Google Groups “wxPython-users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-user...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

I’m not sure - was there code provided I didn’t see it?

Johnf

···

On Wed, Jan 20, 2016 at 9:39 AM, steve oslocourse@gmail.com wrote:

Hi john,

How would you use those statements in Steve’s example?

On Wednesday, January 20, 2016 at 7:26:49 PM UTC+2, johnf wrote:

I’ve run into this in the past and have used one of the following to fix it:
self.SetDoubleBuffered(True)

wx.CallAfter()

On Tue, Jan 19, 2016 at 1:16 PM, steve osloc...@gmail.com wrote:

Hi Chris,

Thank you for the help,

In your first example, it uses Refresh() method to send a EVT_PAINT event, but it causes the drawing area to flash (everything first disappears then reappears), and it doesn’t look good. Isn’t there a better way?

Best regards

You received this message because you are subscribed to the Google Groups “wxPython-users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-user...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

You received this message because you are subscribed to the Google Groups “wxPython-users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Yes, Chris’s first attachment

···

On Wednesday, January 20, 2016 at 7:40:47 PM UTC+2, johnf wrote:

I’m not sure - was there code provided I didn’t see it?

Johnf

On Wed, Jan 20, 2016 at 9:39 AM, steve osloc...@gmail.com wrote:

Hi john,

How would you use those statements in Steve’s example?

On Wednesday, January 20, 2016 at 7:26:49 PM UTC+2, johnf wrote:

I’ve run into this in the past and have used one of the following to fix it:
self.SetDoubleBuffered(True)

wx.CallAfter()

On Tue, Jan 19, 2016 at 1:16 PM, steve osloc...@gmail.com wrote:

Hi Chris,

Thank you for the help,

In your first example, it uses Refresh() method to send a EVT_PAINT event, but it causes the drawing area to flash (everything first disappears then reappears), and it doesn’t look good. Isn’t there a better way?

Best regards

You received this message because you are subscribed to the Google Groups “wxPython-users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-user...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

You received this message because you are subscribed to the Google Groups “wxPython-users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-user...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

AH,

No flashing on the Mac – OS-X is double buffered under the hood anyway.

···

On Wed, Jan 20, 2016 at 9:26 AM, John Fabiani fabiani.john@gmail.com wrote:

I’ve run into this in the past and have used one of the following to fix it:
self.SetDoubleBuffered(True)

cool – I hadn’t seen that call.

wx.CallAfter()

what’s this for?

Please let us know if this works for you.

I think there may also be a style you can set to hlep with this, but I can’t find it at the moment.

-CHB

You received this message because you are subscribed to the Google Groups “wxPython-users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

On Tue, Jan 19, 2016 at 1:16 PM, steve oslocourse@gmail.com wrote:

Hi Chris,

Thank you for the help,

In your first example, it uses Refresh() method to send a EVT_PAINT event, but it causes the drawing area to flash (everything first disappears then reappears), and it doesn’t look good. Isn’t there a better way?

Best regards

You received this message because you are subscribed to the Google Groups “wxPython-users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

First I still do not see your post with code. Maybe it’s my google client?

Anyway, CallAfter (BTW you can check the doc’s) is a way to avoiding a timing issue with other objects updating and your object getting updating at the same time. All it does is delay the update until everything else is finished. Of course there is more to it but in this case that is what it will do for you. As I said earlier it doesn’t always work. Oh! you need to past the refresh or update code to the method.

···

On Wed, Jan 20, 2016 at 1:13 PM, Chris Barker chris.barker@noaa.gov wrote:

AH,

No flashing on the Mac – OS-X is double buffered under the hood anyway.

You received this message because you are subscribed to the Google Groups “wxPython-users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

On Wed, Jan 20, 2016 at 9:26 AM, John Fabiani fabiani.john@gmail.com wrote:

I’ve run into this in the past and have used one of the following to fix it:
self.SetDoubleBuffered(True)

cool – I hadn’t seen that call.

wx.CallAfter()

what’s this for?

Please let us know if this works for you.

I think there may also be a style you can set to hlep with this, but I can’t find it at the moment.

-CHB

You received this message because you are subscribed to the Google Groups “wxPython-users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

On Tue, Jan 19, 2016 at 1:16 PM, steve oslocourse@gmail.com wrote:

Hi Chris,

Thank you for the help,

In your first example, it uses Refresh() method to send a EVT_PAINT event, but it causes the drawing area to flash (everything first disappears then reappears), and it doesn’t look good. Isn’t there a better way?

Best regards

You received this message because you are subscribed to the Google Groups “wxPython-users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Anyway, CallAfter (BTW you can check the doc's) is a way to avoiding a
timing issue with other objects updating and your object getting updating
at the same time.

...

Oh! you need to past the refresh or update code to the method.

OK, that makes sense -- what CallAfter(func) does is put an event on the
event stack that calls func() -- so it's a way to make a function run AFTER
any events that are already on the stack are processed. i.e. it's a way to
run some code after the callback you are in is done.

so yes it can clean up some of these issues.

-CHB

···

On Wed, Jan 20, 2016 at 2:30 PM, John Fabiani <fabiani.john@gmail.com> wrote:

On Wed, Jan 20, 2016 at 1:13 PM, Chris Barker <chris.barker@noaa.gov> > wrote:

AH,

No flashing on the Mac -- OS-X is double buffered under the hood anyway.

On Wed, Jan 20, 2016 at 9:26 AM, John Fabiani <fabiani.john@gmail.com> >> wrote:

I've run into this in the past and have used one of the following to fix
it:
self.SetDoubleBuffered(True)

cool -- I hadn't seen that call.

wx.CallAfter()

what's this for?

Please let us know if this works for you.

I think there may also be a style you can set to hlep with this, but I
can't find it at the moment.

-CHB

On Tue, Jan 19, 2016 at 1:16 PM, steve <oslocourse@gmail.com> wrote:

Hi Chris,

Thank you for the help,

In your first example, it uses Refresh() method to send a EVT_PAINT
event, but it causes the drawing area to flash (everything first disappears
then reappears), and it doesn't look good. Isn't there a better way?

Best regards
--
You received this message because you are subscribed to the Google
Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to wxpython-users+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google
Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to wxpython-users+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov
--
You received this message because you are subscribed to the Google Groups
"wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to wxpython-users+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups
"wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to wxpython-users+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov