OnPaint

Hi there,
I implemented an OnPaint event handler;
the last function it calls is event.Skip().
The good news : it works.
The bad news : in the docs there is
something about an wx.PaintDC.
Is that functional equal ?

Stefan Sonnenberg-Carstens wrote:

Hi there,
I implemented an OnPaint event handler;
the last function it calls is event.Skip().

Don't use Skip in a EVT_PAINT handler unless you want the parent class or the system default handler to still be run. (Most of the time you don't want that.)

The good news : it works.
The bad news : in the docs there is
something about an wx.PaintDC.
Is that functional equal ?

It's a class, and is what you should be using to paint with in the EVT_PAINT handler (or something that uses it, like a wx.BufferedPaintDC.)

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Robin Dunn schrieb:

Stefan Sonnenberg-Carstens wrote:

Hi there,
I implemented an OnPaint event handler;
the last function it calls is event.Skip().

Don't use Skip in a EVT_PAINT handler unless you want the parent class or the system default handler to still be run. (Most of the time you don't want that.)

The good news : it works.
The bad news : in the docs there is
something about an wx.PaintDC.
Is that functional equal ?

It's a class, and is what you should be using to paint with in the EVT_PAINT handler (or something that uses it, like a wx.BufferedPaintDC.)

Mh, I already draw to an DC in OnPaint.
But when I omit the event.Skip() the gui will not close anymore.
So this time I want ?

Stefan Sonnenberg-Carstens wrote:

Robin Dunn schrieb:

Stefan Sonnenberg-Carstens wrote:

Hi there,
I implemented an OnPaint event handler;
the last function it calls is event.Skip().

Don't use Skip in a EVT_PAINT handler unless you want the parent class or the system default handler to still be run. (Most of the time you don't want that.)

The good news : it works.
The bad news : in the docs there is
something about an wx.PaintDC.
Is that functional equal ?

It's a class, and is what you should be using to paint with in the EVT_PAINT handler (or something that uses it, like a wx.BufferedPaintDC.)

Mh, I already draw to an DC in OnPaint.
But when I omit the event.Skip() the gui will not close anymore.

With a wx.PaintDC or some other kind? You must create and use a wx.PaintDC in the EVT_PAINT event, otherwise the system could assume that you didn't fully refresh the window and immediately send the event again (and again, and...)

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Robin Dunn schrieb:

Stefan Sonnenberg-Carstens wrote:

Robin Dunn schrieb:

Stefan Sonnenberg-Carstens wrote:

Hi there,
I implemented an OnPaint event handler;
the last function it calls is event.Skip().

Don't use Skip in a EVT_PAINT handler unless you want the parent class or the system default handler to still be run. (Most of the time you don't want that.)

The good news : it works.
The bad news : in the docs there is
something about an wx.PaintDC.
Is that functional equal ?

It's a class, and is what you should be using to paint with in the EVT_PAINT handler (or something that uses it, like a wx.BufferedPaintDC.)

Mh, I already draw to an DC in OnPaint.
But when I omit the event.Skip() the gui will not close anymore.

With a wx.PaintDC or some other kind? You must create and use a wx.PaintDC in the EVT_PAINT event, otherwise the system could assume that you didn't fully refresh the window and immediately send the event again (and again, and...)

It was a WindowDC.
I changed the code and it does not work either.
I must use event.Skip() ...

Stefan Sonnenberg-Carstens wrote:

Robin Dunn schrieb:

Stefan Sonnenberg-Carstens wrote:

Mh, I already draw to an DC in OnPaint.
But when I omit the event.Skip() the gui will not close anymore.

With a wx.PaintDC or some other kind? You must create and use a wx.PaintDC in the EVT_PAINT event, otherwise the system could assume that you didn't fully refresh the window and immediately send the event again (and again, and...)

It was a WindowDC.
I changed the code and it does not work either.
I must use event.Skip() ...

Please create a small sample app that shows the problem.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Robin Dunn schrieb:

Stefan Sonnenberg-Carstens wrote:

Robin Dunn schrieb:

Stefan Sonnenberg-Carstens wrote:

Mh, I already draw to an DC in OnPaint.
But when I omit the event.Skip() the gui will not close anymore.

With a wx.PaintDC or some other kind? You must create and use a wx.PaintDC in the EVT_PAINT event, otherwise the system could assume that you didn't fully refresh the window and immediately send the event again (and again, and...)

It was a WindowDC.
I changed the code and it does not work either.
I must use event.Skip() ...

Please create a small sample app that shows the problem.

# Under windows xp sp2, python 2.3.5 and wxpython 2.6 it consumes loads
# of CPU power and is not closeable
# un-comment the line with the event.Skip() and everything works as expected

import wx

class OnPaintFrame(wx.Frame):

    def __init__(self,parent=None,title='OnDrawFrame'):
        wx.Frame.__init__(self,parent,-1,title)
        self.panel = wx.Panel(self)
        self.Bind(wx.EVT_CLOSE,self.OnClose)
        self.Bind(wx.EVT_PAINT,self.OnPaint)

    def OnClose(self,event):
        self.Destroy()

    def OnPaint(self,event):
        dc = wx.PaintDC(self.panel)
        self.panel.PrepareDC(dc)
        dc.Clear()
        dc.DrawRectangle(20,20,50,50)
        #event.Skip()
       app = wx.App()
f = OnPaintFrame()
app.SetTopWindow(f)
f.Show()
app.MainLoop()

Hi Stefan,

       self.panel = wx.Panel(self)
       self.Bind(wx.EVT_CLOSE,self.OnClose)
       self.Bind(wx.EVT_PAINT,self.OnPaint)

You are binding the Paint event to the frame, so why are you calling:

       dc = wx.PaintDC(self.panel)

On the panel? If you want to handle the OnPaint for the panel, you should do:

self.panel.Bind(wx.EVT_PAINT, self.OnPaint)

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.virgilio.it/infinity77/

Andrea Gavana wrote:

You are binding the Paint event to the frame, so why are you calling:

       dc = wx.PaintDC(self.panel)

On the panel?

Which is why this structure is not recommended. I think the PrepareDC() call in only required for ScrolledWindows, etc.

A style like the bow will make for more reusable code, and less confusion and errors. see item (7) in:

http://wiki.wxpython.org/index.cgi/wxPython_Style_Guide

#!/usr/bin/env python
import wx

class OnPaintPanel(wx.Panel):

    def __init__(self,*args, **kwargs):
        wx.Panel.__init__(self,*args, **kwargs)

        self.Bind(wx.EVT_PAINT,self.OnPaint)

    def OnPaint(self,event):
        dc = wx.PaintDC(self)
        dc.Clear()
        dc.DrawRectangle(20,20,50,50)

class OnPaintFrame(wx.Frame):

    def __init__(self,parent=None,title='OnDrawFrame'):
        wx.Frame.__init__(self,parent,-1,title)

        self.panel = OnPaintPanel(self)
        self.Bind(wx.EVT_CLOSE,self.OnClose)

    def OnClose(self,event):
        self.Destroy()

app = wx.App()
f = OnPaintFrame()
app.SetTopWindow(f)

···

--
Christopher Barker, Ph.D.
Oceanographer
                                         
NOAA/OR&R/HAZMAT (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

Andrea Gavana schrieb:

Hi Stefan,

       self.panel = wx.Panel(self)
       self.Bind(wx.EVT_CLOSE,self.OnClose)
       self.Bind(wx.EVT_PAINT,self.OnPaint)

You are binding the Paint event to the frame, so why are you calling:

       dc = wx.PaintDC(self.panel)

On the panel? If you want to handle the OnPaint for the panel, you should do:

self.panel.Bind(wx.EVT_PAINT, self.OnPaint)

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.virgilio.it/infinity77/

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

which solved the problem, thanks :slight_smile:

Christopher Barker schrieb:

Andrea Gavana wrote:

You are binding the Paint event to the frame, so why are you calling:

       dc = wx.PaintDC(self.panel)

On the panel?

Which is why this structure is not recommended. I think the PrepareDC() call in only required for ScrolledWindows, etc.

A style like the bow will make for more reusable code, and less confusion and errors. see item (7) in:

http://wiki.wxpython.org/index.cgi/wxPython_Style_Guide

#!/usr/bin/env python
import wx

class OnPaintPanel(wx.Panel):

   def __init__(self,*args, **kwargs):
       wx.Panel.__init__(self,*args, **kwargs)

       self.Bind(wx.EVT_PAINT,self.OnPaint)

   def OnPaint(self,event):
       dc = wx.PaintDC(self)
       dc.Clear()
       dc.DrawRectangle(20,20,50,50)

class OnPaintFrame(wx.Frame):

   def __init__(self,parent=None,title='OnDrawFrame'):
       wx.Frame.__init__(self,parent,-1,title)

       self.panel = OnPaintPanel(self)
       self.Bind(wx.EVT_CLOSE,self.OnClose)

   def OnClose(self,event):
       self.Destroy()

app = wx.App()
f = OnPaintFrame()
app.SetTopWindow(f)

which would not saved me from the error i made.
it looks better, indeed. with your code it is obvious that
OnPaint belongs to the panel.
I thought, that the OnPaint is something more global,
but i ended up to be somewhat confused about the usage of
the "window" term in wxwidgets/python.

Andrea Gavana wrote:
> You are binding the Paint event to the frame, so why are you calling:
>
>> dc = wx.PaintDC(self.panel)
>
> On the panel?

Which is why this structure is not recommended.

This is just a matter of personal taste. AFAIK, both approaches work.
The question was just *why* that particular code didn't work. If then
we move the discussion to coding styles, I agree with you that having
separate classes to handle these situations is far nicer/reusable/less
error-prone.

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.virgilio.it/infinity77/

Andrea Gavana wrote:

Which is why this structure is not recommended.

This is just a matter of personal taste.

Well, I like to think that it's a bit more than just taste. It is a matter of opinion, but I think clean, robust coding style can be assessed objectively.

> AFAIK, both approaches work.

well, sure. so does this:

#!/usr/bin/env python
import wx

app = wx.App()
f = wx.Frame(None)
p = wx.Panel(f)
def Paint(event):
    dc = wx.PaintDC(p)
    dc.Clear()
    dc.DrawRectangle(20,20,50,50)
p.Bind(wx.EVT_PAINT, Paint)
app.SetTopWindow(f)
f.Show()
app.MainLoop()

But I doubt anyone would recommend that style.

The question was just *why* that particular code didn't work.

Which you did answer perfectly accurately.

> If then we move the discussion to coding styles,

Which was my intent.

The folks coming to this list are new to wxPython, and often also new to Python, and even new to programming and/or OO programming. I've kind of taken it upon my self to help encourage good coding style as early as possible. People will have better code and make fewer errors, the sooner they learn.

In fact, though the OP indicated that my proposed style would not have prevented the error, I'm not so sure -- he was (as was I, when I started) a bit confused about what the heck a wx.Window (vs. a wx.Panel, vs a wx.Frame) was -- that style makes the whole Frame-Panel-Window relationships more clear.

Just as a note, as it still may not be so clear -- you could accomplish the same thing without a Panel at all:

app = wx.App()
f = wx.Frame(None)
def Paint(event):
    dc = wx.PaintDC(f)
    dc.Clear()
    dc.DrawRectangle(20,20,50,50)
f.Bind(wx.EVT_PAINT, Paint)
app.SetTopWindow(f)
f.Show()
app.MainLoop()

The reason to add a Panel is if you want to put other controls on it, catch mouse events, etc, and/or want to put it on other Frames, Windows, etc. -- in that case, you'll really want a separate class.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                         
NOAA/OR&R/HAZMAT (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