GraphicsContext inside a PyAUI pane fails when it's docked

I have a panel which is inside a PyAUI pane. (It's not an immediate
child, I think 3 or 4 layers of panels between them.)

I used to have the `OnPaint` of this panel draw with a PaintDC. Now
I'm trying to use a GraphicsContext to draw on that DC. I put in some
code to draw a simple red circle:

dc = wx.PaintDC(self)
# ... Here I draw some bitmap to the dc
gc = wx.GraphicsContext.Create(dc)
gc.SetPen(wx.Pen(wx.NamedColor('Red'), 20))
gc.DrawEllipse(5,5,2,2)

When I launch the app, the pane starts docked, and I don't see the red
circle. I float the pane, then I see the circle on top of the bitmap
as it should be. I can move it around and I still see the circle. I
dock it again, no matter where, and the circle disappears, and only
the bitmap remains.

What could cause this?

Ram.

···

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

Don't know. Can you make a runnable sample for it?

···

On 4/8/10 4:16 PM, cool-RR wrote:

I have a panel which is inside a PyAUI pane. (It's not an immediate
child, I think 3 or 4 layers of panels between them.)

I used to have the `OnPaint` of this panel draw with a PaintDC. Now
I'm trying to use a GraphicsContext to draw on that DC. I put in some
code to draw a simple red circle:

dc = wx.PaintDC(self)
# ... Here I draw some bitmap to the dc
gc = wx.GraphicsContext.Create(dc)
gc.SetPen(wx.Pen(wx.NamedColor('Red'), 20))
gc.DrawEllipse(5,5,2,2)

When I launch the app, the pane starts docked, and I don't see the red
circle. I float the pane, then I see the circle on top of the bitmap
as it should be. I can move it around and I still see the circle. I
dock it again, no matter where, and the circle disappears, and only
the bitmap remains.

What could cause this?

--
Robin Dunn
Software Craftsman

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

I tried reproducing it in a bare PyAUI, but it didn’t happen.

Here’s a YouTube clip:

http://www.youtube.com/watch?v=r3aAGAWKsH8

(You should probably press the 480p quality button there to see it in higher resolution.)

If you want you can download and run my program here to see how it happens:

http://github.com/cool-RR/GarlicSim/zipball/b12edb7dce7d3229c439efb7926b0dd48d2975bd

The offending widget is at garlicsim_wx\garlicsim_wx\widgets\general_misc\knob\knob.py.

Ram.

···

On Fri, Apr 9, 2010 at 1:57 AM, Robin Dunn robin@alldunn.com wrote:

On 4/8/10 4:16 PM, cool-RR wrote:

I have a panel which is inside a PyAUI pane. (It’s not an immediate

child, I think 3 or 4 layers of panels between them.)

I used to have the OnPaint of this panel draw with a PaintDC. Now

I’m trying to use a GraphicsContext to draw on that DC. I put in some

code to draw a simple red circle:

dc = wx.PaintDC(self)

… Here I draw some bitmap to the dc

gc = wx.GraphicsContext.Create(dc)

gc.SetPen(wx.Pen(wx.NamedColor(‘Red’), 20))

gc.DrawEllipse(5,5,2,2)

When I launch the app, the pane starts docked, and I don’t see the red

circle. I float the pane, then I see the circle on top of the bitmap

as it should be. I can move it around and I still see the circle. I

dock it again, no matter where, and the circle disappears, and only

the bitmap remains.

What could cause this?

Don’t know. Can you make a runnable sample for it?

Robin Dunn

Hi,

I have a panel which is inside a PyAUI pane. (It's not an immediate
child, I think 3 or 4 layers of panels between them.)

I used to have the `OnPaint` of this panel draw with a PaintDC. Now
I'm trying to use a GraphicsContext to draw on that DC. I put in some
code to draw a simple red circle:

dc = wx.PaintDC(self)
# ... Here I draw some bitmap to the dc
gc = wx.GraphicsContext.Create(dc)
gc.SetPen(wx.Pen(wx.NamedColor('Red'), 20))
gc.DrawEllipse(5,5,2,2)

When I launch the app, the pane starts docked, and I don't see the red
circle. I float the pane, then I see the circle on top of the bitmap
as it should be. I can move it around and I still see the circle. I
dock it again, no matter where, and the circle disappears, and only
the bitmap remains.

What could cause this?

Don't know. Can you make a runnable sample for it?

--
Robin Dunn

I tried reproducing it in a bare PyAUI, but it didn't happen.
Here's a YouTube clip:
http://www.youtube.com/watch?v=r3aAGAWKsH8
(You should probably press the 480p quality button there to see it in higher
resolution.)
If you want you can download and run my program here to see how it happens:
http://github.com/cool-RR/GarlicSim/zipball/b12edb7dce7d3229c439efb7926b0dd48d2975bd

The offending widget is at
garlicsim_wx\garlicsim_wx\widgets\general_misc\knob\knob.py.

Not sure what is going on, but you might try a couple of things (not
sure they help anyway):

1) Don't call event.Skip() in your on_paint handler;
2) Create an empty OnEraseBackground handler for your panel, i.e.:

self.Bind(wx.EVT_ERASE_BACKGROUND, self.on_erase)

def on_erase(self, event):
    pass

And use wx.BufferedPaintDC instead of wx.PaintDC in your on_paint handler.

3) Bind a size event for your panel, i.e.:

self.Bind(wx.EVT_SIZE, self.on_size)

def on_size(self, event):
    self.Refersh()
    event.Skip()

4) Use a wx.PyPanel/wx.PyControl instead of a plain wx.Panel (see the AUI demo).

Andrea.

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

==> Never *EVER* use RemovalGroup for your house removal. You'll
regret it forever.
The Doomed City: Removal Group: the nightmare <==

···

On 9 April 2010 10:23, cool-RR wrote:

On Fri, Apr 9, 2010 at 1:57 AM, Robin Dunn <robin@alldunn.com> wrote:

On 4/8/10 4:16 PM, cool-RR wrote:

The second half of your suggestion number 2 did the trick: I replaced the PaintDC with a BufferedPaintDC.

Thanks!

···

On Fri, Apr 9, 2010 at 11:39 AM, Andrea Gavana andrea.gavana@gmail.com wrote:

Hi,

Not sure what is going on, but you might try a couple of things (not

sure they help anyway):

  1. Don’t call event.Skip() in your on_paint handler;

  2. Create an empty OnEraseBackground handler for your panel, i.e.:

self.Bind(wx.EVT_ERASE_BACKGROUND, self.on_erase)

def on_erase(self, event):

pass

And use wx.BufferedPaintDC instead of wx.PaintDC in your on_paint handler.

  1. Bind a size event for your panel, i.e.:

self.Bind(wx.EVT_SIZE, self.on_size)

def on_size(self, event):

self.Refersh()

event.Skip()
  1. Use a wx.PyPanel/wx.PyControl instead of a plain wx.Panel (see the AUI demo).

Andrea.

Now I have a slight problem though. Even though I did not mess with EVT_ERASE_BACKGROUND, it seems like my background is not getting erased every time the widget gets redrawn. What can I do? What’s the preferred way to erase the background of a widget?

Ram.

···

On Fri, Apr 9, 2010 at 1:04 PM, cool-RR cool-rr@cool-rr.com wrote:

On Fri, Apr 9, 2010 at 11:39 AM, Andrea Gavana andrea.gavana@gmail.com wrote:

Hi,

Not sure what is going on, but you might try a couple of things (not

sure they help anyway):

  1. Don’t call event.Skip() in your on_paint handler;

  2. Create an empty OnEraseBackground handler for your panel, i.e.:

self.Bind(wx.EVT_ERASE_BACKGROUND, self.on_erase)

def on_erase(self, event):

pass

And use wx.BufferedPaintDC instead of wx.PaintDC in your on_paint handler.

  1. Bind a size event for your panel, i.e.:

self.Bind(wx.EVT_SIZE, self.on_size)

def on_size(self, event):

self.Refersh()

event.Skip()
  1. Use a wx.PyPanel/wx.PyControl instead of a plain wx.Panel (see the AUI demo).

Andrea.

The second half of your suggestion number 2 did the trick: I replaced the PaintDC with a BufferedPaintDC.

Thanks!

Hi,

Hi,

Not sure what is going on, but you might try a couple of things (not
sure they help anyway):

1) Don't call event.Skip() in your on_paint handler;
2) Create an empty OnEraseBackground handler for your panel, i.e.:

self.Bind(wx.EVT_ERASE_BACKGROUND, self.on_erase)

def on_erase(self, event):
pass

And use wx.BufferedPaintDC instead of wx.PaintDC in your on_paint
handler.

3) Bind a size event for your panel, i.e.:

self.Bind(wx.EVT_SIZE, self.on_size)

def on_size(self, event):
self.Refersh()
event.Skip()

4) Use a wx.PyPanel/wx.PyControl instead of a plain wx.Panel (see the AUI
demo).

Andrea.

The second half of your suggestion number 2 did the trick: I replaced the
PaintDC with a BufferedPaintDC.
Thanks!

Now I have a slight problem though. Even though I did not mess with
EVT_ERASE_BACKGROUND, it seems like my background is not getting erased
every time the widget gets redrawn. What can I do? What's the preferred way
to erase the background of a widget?

Bind the wx.EVT_ERASE_BACKGROUND event as I said above.
wx.BufferedPaintDC is made for exactly this purpose.

Andrea.

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

==> Never *EVER* use RemovalGroup for your house removal. You'll
regret it forever.
The Doomed City: Removal Group: the nightmare <==

···

On 9 April 2010 12:19, cool-RR <cool-rr@cool-rr.com> wrote:

On Fri, Apr 9, 2010 at 1:04 PM, cool-RR <cool-rr@cool-rr.com> wrote:

On Fri, Apr 9, 2010 at 11:39 AM, Andrea Gavana <andrea.gavana@gmail.com> >> wrote:

Did it now, still getting a black background.

Ram.

···

On Fri, Apr 9, 2010 at 1:26 PM, Andrea Gavana andrea.gavana@gmail.com wrote:

Hi,

On 9 April 2010 12:19, cool-RR cool-rr@cool-rr.com wrote:

On Fri, Apr 9, 2010 at 1:04 PM, cool-RR cool-rr@cool-rr.com wrote:

On Fri, Apr 9, 2010 at 11:39 AM, Andrea Gavana andrea.gavana@gmail.com > > >> wrote:

Hi,

Not sure what is going on, but you might try a couple of things (not

sure they help anyway):

  1. Don’t call event.Skip() in your on_paint handler;
  1. Create an empty OnEraseBackground handler for your panel, i.e.:

self.Bind(wx.EVT_ERASE_BACKGROUND, self.on_erase)

def on_erase(self, event):

pass

And use wx.BufferedPaintDC instead of wx.PaintDC in your on_paint

handler.

  1. Bind a size event for your panel, i.e.:

self.Bind(wx.EVT_SIZE, self.on_size)

def on_size(self, event):

self.Refersh()

event.Skip()

  1. Use a wx.PyPanel/wx.PyControl instead of a plain wx.Panel (see the AUI

demo).

Andrea.

The second half of your suggestion number 2 did the trick: I replaced the

PaintDC with a BufferedPaintDC.

Thanks!

Now I have a slight problem though. Even though I did not mess with

EVT_ERASE_BACKGROUND, it seems like my background is not getting erased

every time the widget gets redrawn. What can I do? What’s the preferred way

to erase the background of a widget?

Bind the wx.EVT_ERASE_BACKGROUND event as I said above.

wx.BufferedPaintDC is made for exactly this purpose.

Andrea.

This is because by handling the EVT_PAINT and EVT_ERASE_BACKGROUND you
have to take care of drawing the background yourself in your on_paint
method. Almost all the pure-Python widgets in wx.lib (and all the AGW
widgets) use this technique. If you look at the source you'll see it's
not that complex.

Andrea.

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

==> Never *EVER* use RemovalGroup for your house removal. You'll
regret it forever.
The Doomed City: Removal Group: the nightmare <==

···

On 9 April 2010 12:42, cool-RR <cool-rr@cool-rr.com> wrote:

On Fri, Apr 9, 2010 at 1:26 PM, Andrea Gavana <andrea.gavana@gmail.com> > wrote:

Hi,

On 9 April 2010 12:19, cool-RR <cool-rr@cool-rr.com> wrote:
>
>
> On Fri, Apr 9, 2010 at 1:04 PM, cool-RR <cool-rr@cool-rr.com> wrote:
>>
>>
>> On Fri, Apr 9, 2010 at 11:39 AM, Andrea Gavana >> >> <andrea.gavana@gmail.com> >> >> wrote:
>>>
>>> Hi,
>>>
>>>
>>> Not sure what is going on, but you might try a couple of things (not
>>> sure they help anyway):
>>>
>>> 1) Don't call event.Skip() in your on_paint handler;
>>> 2) Create an empty OnEraseBackground handler for your panel, i.e.:
>>>
>>> self.Bind(wx.EVT_ERASE_BACKGROUND, self.on_erase)
>>>
>>> def on_erase(self, event):
>>> pass
>>>
>>> And use wx.BufferedPaintDC instead of wx.PaintDC in your on_paint
>>> handler.
>>>
>>> 3) Bind a size event for your panel, i.e.:
>>>
>>> self.Bind(wx.EVT_SIZE, self.on_size)
>>>
>>> def on_size(self, event):
>>> self.Refersh()
>>> event.Skip()
>>>
>>> 4) Use a wx.PyPanel/wx.PyControl instead of a plain wx.Panel (see the
>>> AUI
>>> demo).
>>>
>>> Andrea.
>>>
>>
>> The second half of your suggestion number 2 did the trick: I replaced
>> the
>> PaintDC with a BufferedPaintDC.
>> Thanks!
>
>
> Now I have a slight problem though. Even though I did not mess with
> EVT_ERASE_BACKGROUND, it seems like my background is not getting erased
> every time the widget gets redrawn. What can I do? What's the preferred
> way
> to erase the background of a widget?

Bind the wx.EVT_ERASE_BACKGROUND event as I said above.
wx.BufferedPaintDC is made for exactly this purpose.

Andrea.

Did it now, still getting a black background.

Okay, I’ve done it and it works.

Thanks, Ram.

···

On Fri, Apr 9, 2010 at 2:02 PM, Andrea Gavana andrea.gavana@gmail.com wrote:

On 9 April 2010 12:42, cool-RR cool-rr@cool-rr.com wrote:

On Fri, Apr 9, 2010 at 1:26 PM, Andrea Gavana andrea.gavana@gmail.com > > > wrote:

Hi,

On 9 April 2010 12:19, cool-RR cool-rr@cool-rr.com wrote:

On Fri, Apr 9, 2010 at 1:04 PM, cool-RR cool-rr@cool-rr.com wrote:

On Fri, Apr 9, 2010 at 11:39 AM, Andrea Gavana > > >> >> andrea.gavana@gmail.com > > >> >> wrote:

Hi,

Not sure what is going on, but you might try a couple of things (not

sure they help anyway):

  1. Don’t call event.Skip() in your on_paint handler;
  1. Create an empty OnEraseBackground handler for your panel, i.e.:

self.Bind(wx.EVT_ERASE_BACKGROUND, self.on_erase)

def on_erase(self, event):

pass

And use wx.BufferedPaintDC instead of wx.PaintDC in your on_paint

handler.

  1. Bind a size event for your panel, i.e.:

self.Bind(wx.EVT_SIZE, self.on_size)

def on_size(self, event):

self.Refersh()

event.Skip()

  1. Use a wx.PyPanel/wx.PyControl instead of a plain wx.Panel (see the

AUI

demo).

Andrea.

The second half of your suggestion number 2 did the trick: I replaced

the

PaintDC with a BufferedPaintDC.

Thanks!

Now I have a slight problem though. Even though I did not mess with

EVT_ERASE_BACKGROUND, it seems like my background is not getting erased

every time the widget gets redrawn. What can I do? What’s the preferred

way

to erase the background of a widget?

Bind the wx.EVT_ERASE_BACKGROUND event as I said above.

wx.BufferedPaintDC is made for exactly this purpose.

Andrea.

Did it now, still getting a black background.

This is because by handling the EVT_PAINT and EVT_ERASE_BACKGROUND you

have to take care of drawing the background yourself in your on_paint

method. Almost all the pure-Python widgets in wx.lib (and all the AGW

widgets) use this technique. If you look at the source you’ll see it’s

not that complex.

Andrea.