Custom container control?

Hey, all–

I’m working on a custom container control, basically a new wx.Panel that I can put on a frame that contains various other controls. However, I want to draw some stuff on it for some special behaviors. Soo, I would like to set the area that the sizers and such are free to start filling in.

I just can’t quite figure out how to do that :slight_smile:

I can override DoGetClientSize from wx.PyPanel and shrink the size of what the available area is, but I can’t set where it should /start/. Looking around, it seems I want to override wxWindow.GetClientAreaOrigin … but I can’t :slight_smile: (I tried subclassing from wx.pyWindow too and calling DoGetClientAreaOrigin, still no go.)

Am I going about this the right way?

Basically, if I have a square control that is (100, 100) in size, I don’t want the top 10 pixels to ever get messed with. It isn’t a part of the “client area”. I can probably fudge it with some careful sizer-border doohickery, but that just doesn’t quite seem right.

Thanks in advance.

–S

I think you may be tackling this in the wrong manner.

Are the custom bits of the panel rectangular? If so,
then don't make the panel custom. Instead, make the
panel just a wxPanel, use sizers to place rectangular
things on it, and make some of the things custom items
that subclass wxWindow.

On your custom items, call SetMinSize after
construction so they know how big they should be and
the sizers will do the heavy lifting. Have the custom
bits bind their EVT_PAINT to handle their drawing.

The nice thing about this approach is that all the
custom bits draw from the origin of 0,0. wxPython
handles all the coordinate translation, so you don't
have to worry about where the custom item is.

Non-rectangular items can be done, but they're not
quite as simple. Must the areas be non-rectangular?

Gre7g

···

--- Stephen Hansen <apt.shansen@gmail.com> wrote:

Hey, all--

I'm working on a custom container control, basically
a new wx.Panel that I
can put on a frame that contains various other
controls. However, I want to
draw some stuff on it for some special behaviors.
Soo, I would like to set
the area that the sizers and such are free to start
filling in.

I just can't quite figure out how to do that :slight_smile:

I can override DoGetClientSize from wx.PyPanel and
shrink the size of what
the available area is, but I can't set where it
should /start/. Looking
around, it seems I want to override
wxWindow.GetClientAreaOrigin .. but I
can't :slight_smile: (I tried subclassing from wx.pyWindow too
and calling
DoGetClientAreaOrigin, still no go.)

Am I going about this the right way?

Basically, if I have a square control that is (100,
100) in size, I don't
want the top 10 pixels to ever get messed with. It
isn't a part of the
"client area". I can probably fudge it with some
careful sizer-border
doohickery, but that just doesn't quite seem right.

Thanks in advance.

--S

      ____________________________________________________________________________________
Fussy? Opinionated? Impossible to please? Perfect. Join Yahoo!'s user panel and lay it on us. http://surveylink.yahoo.com/gmrs/yahoo_panel_invite.asp?a=7

More thoughts -

If your panel is truly a custom container instead of
just needing rectangular custom bits, then consider
making an internal sizer and overriding the various
SetSizer methods. For example, let's say a simple
sizer that just adds a border of 20 pixels on all
sides.

Now when code instantiates your custom control, they
will create child objects, stick them in a sizer, and
pass you the sizer by calling SetSizerAndFit. You
take your internal sizer, stick their sizer inside it
and connect it up.

This won't work in all ways because the user can do a
GetSizer and they'll see your internal one, but if
this isn't a general purpose control for everyone to
use, then it may be adequate.

HTH,
Gre7g

···

--- Stephen Hansen <apt.shansen@gmail.com> wrote:

Hey, all--

I'm working on a custom container control, basically
a new wx.Panel that I
can put on a frame that contains various other
controls. However, I want to
draw some stuff on it for some special behaviors.
Soo, I would like to set
the area that the sizers and such are free to start
filling in.

I just can't quite figure out how to do that :slight_smile:

I can override DoGetClientSize from wx.PyPanel and
shrink the size of what
the available area is, but I can't set where it
should /start/. Looking
around, it seems I want to override
wxWindow.GetClientAreaOrigin .. but I
can't :slight_smile: (I tried subclassing from wx.pyWindow too
and calling
DoGetClientAreaOrigin, still no go.)

Am I going about this the right way?

Basically, if I have a square control that is (100,
100) in size, I don't
want the top 10 pixels to ever get messed with. It
isn't a part of the
"client area". I can probably fudge it with some
careful sizer-border
doohickery, but that just doesn't quite seem right.

Thanks in advance.

--S

____________________________________________________________________________________
Moody friends. Drama queens. Your life? Nope! - their life, your story. Play Sims Stories at Yahoo! Games.
http://sims.yahoo.com/

The custom bits are the panel itself :slight_smile:

Attached is a dummy I quickly threw together for what I’m trying to do. It all works as it /is/, a nice little panel that resizes itself, ahs a little title, and a a little close button.

The problem is the children decide to just take up all of the space in there :slight_smile:

Dummy.jpg

···

On 6/30/07, Gre7g Luterman < hafeliel@yahoo.com> wrote:

I think you may be tackling this in the wrong manner.

Are the custom bits of the panel rectangular? If so,
then don’t make the panel custom. Instead, make the
panel just a wxPanel, use sizers to place rectangular
things on it, and make some of the things custom items

that subclass wxWindow.

On your custom items, call SetMinSize after
construction so they know how big they should be and
the sizers will do the heavy lifting. Have the custom
bits bind their EVT_PAINT to handle their drawing.

The nice thing about this approach is that all the
custom bits draw from the origin of 0,0. wxPython
handles all the coordinate translation, so you don’t
have to worry about where the custom item is.

Non-rectangular items can be done, but they’re not
quite as simple. Must the areas be non-rectangular?

Gre7g

— Stephen Hansen <apt.shansen@gmail.com

wrote:

Hey, all–

I’m working on a custom container control, basically
a new wx.Panel that I
can put on a frame that contains various other
controls. However, I want to

draw some stuff on it for some special behaviors.
Soo, I would like to set
the area that the sizers and such are free to start
filling in.

I just can’t quite figure out how to do that :slight_smile:

I can override DoGetClientSize from wx.PyPanel and
shrink the size of what
the available area is, but I can’t set where it
should /start/. Looking
around, it seems I want to override

wxWindow.GetClientAreaOrigin … but I
can’t :slight_smile: (I tried subclassing from wx.pyWindow too
and calling
DoGetClientAreaOrigin, still no go.)

Am I going about this the right way?

Basically, if I have a square control that is (100,
100) in size, I don’t
want the top 10 pixels to ever get messed with. It
isn’t a part of the
“client area”. I can probably fudge it with some

careful sizer-border
doohickery, but that just doesn’t quite seem right.

Thanks in advance.

–S

  ____________________________________________________________________________________

Fussy? Opinionated? Impossible to please? Perfect. Join Yahoo!'s user panel and lay it on us. http://surveylink.yahoo.com/gmrs/yahoo_panel_invite.asp?a=7


To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org

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


Stephen Hansen
Development

Advanced Prepress Technology

shansen@advpubtech.com
(818) 748-9282

Gotcha. Yeah, I'd try the internal sizer and
replacing the SetSizer-type-methods. It may not be
the most elegant idea, but it should work.

Gre7g

···

--- Stephen Hansen <apt.shansen@gmail.com> wrote:

The custom bits are the panel itself :slight_smile:

Attached is a dummy I quickly threw together for
what I'm trying to do. It
all works as it /is/, a nice little panel that
resizes itself, ahs a little
title, and a a little close button.

The problem is the children decide to just take up
all of the space in there
:slight_smile:

____________________________________________________________________________________
No need to miss a message. Get email on-the-go
with Yahoo! Mail for Mobile. Get started.

Gotcha. Yeah, I’d try the internal sizer and
replacing the SetSizer-type-methods. It may not be

the most elegant idea, but it should work.

That actually worked pretty well. The goal is a control that is at least fairly-generic and fairly easy to use in place of any other panel, and that’s why I was looking at some yay to just override the client area. Buut, the internal sizers ended up working well. (I had to have two in the end, so I could have a deeper TOP border then the LEFT/BOTTOM/RIGHT ones that I had to set for the roundness. But that’s easy)

In making my custom control here I did run into another problem though; if I add multiple ones to the same parent, only the first one gets the background painted. But other stuff /is/ being painted… just not the background.

Attached is a sample file with the rounded panel in it. Anyone have any ideas? :slight_smile:

As an aside, I did notice one interesting thing that tells me I simply don’t understand painting …

If I create my context via:

    dc = wx.PaintDC(self)
    gc = wx.GraphicsContext.Create(dc)

then the behavior is that only the first of the rounded panels gets its background.

But, if I create it via:
dc = wx.BufferedPaintDC
(self)
gc = wx.GraphicsContext.Create(dc)

Then they all get a background. However, each subsequent one starts with where the last left off so the first one looks fine; the second one has the first + second’s text written in the same place, etc, etc.

I’m thinking somehow I’m getting some line crossed.

Thanks again!

Oh, and if it matters: I’m on OSX w/ Python 2.4 and wxPython 2.8latest-ish.

–S

test2.py (6.08 KB)

That actually worked pretty well. The goal is a
control that is at least
fairly-generic and fairly easy to use in place of
any other panel, and
that's why I was looking at some yay to just
override the client area. Buut,
the internal sizers ended up working well. (I had to
have two in the end, so
I could have a deeper TOP border then the
LEFT/BOTTOM/RIGHT ones that I had
to set for the roundness. But that's easy)

You can do this with one sizer, just add a spacer to
buy some extra pixels.

In making my custom control here I did run into
another problem though; if I
add multiple ones to the same parent, only the first
one gets the background
painted. But other stuff /is/ being painted... just
not the background.

The problem is that you're trying to use the parent's
coordinate system instead of the local coords. In
each of your custom windows, the origin will be 0,0.
This is true even of windows 2, 3, and 4.

Attached is a sample file with the rounded panel in
it. Anyone have any
ideas? :slight_smile:

I'll attach a patch to fix that one problem. There
are however:

[1] You still need to paint the area outside the
rounded rectangle. Your OnPaint is responsible for
the entire rectangle within your panel, not just the
parts you want to do.

[2] Do not make the client area of your custom window
smaller than the window size. If the owner wants a
smaller window, then they should use sizers to add
space around the custom window.

[3] You're doing more work than you really need to.
Think of how much simpler your code would be if you
just drew the rounded rect with your paint code! The
title could be wxStaticText. The close button could
be a wxBitmapButton. Use your sizers to place these
and make life easier.

Gre7g

diff.txt (717 Bytes)

···

--- Stephen Hansen <apt.shansen@gmail.com> wrote:

____________________________________________________________________________________
Looking for a deal? Find great prices on flights and hotels with Yahoo! FareChase.
http://farechase.yahoo.com/

In making my custom control here I did run into
another problem though; if I

add multiple ones to the same parent, only the first
one gets the background
painted. But other stuff /is/ being painted… just
not the background.

The problem is that you’re trying to use the parent’s

coordinate system instead of the local coords. In
each of your custom windows, the origin will be 0,0.
This is true even of windows 2, 3, and 4.

… Doh. I totally wasn’t thinking when I snagged the rect. That all makes sense now :stuck_out_tongue:

Attached is a sample file with the rounded panel in
it. Anyone have any

ideas? :slight_smile:

I’ll attach a patch to fix that one problem. There
are however:

[1] You still need to paint the area outside the
rounded rectangle. Your OnPaint is responsible for
the entire rectangle within your panel, not just the

parts you want to do.

Ah, the wxDC version I wrote initially did that. And on the mac it looks just fine in the middle of the program, so I forgot to re-do it in the wxGraphicsContext version.

[2] Do not make the client area of your custom window
smaller than the window size. If the owner wants a

smaller window, then they should use sizers to add
space around the custom window.

Whoops, I forgot to take that out. It was there back from when I was trying to use it in combination with overriding the origin of the client area.

[3] You’re doing more work than you really need to.
Think of how much simpler your code would be if you

just drew the rounded rect with your paint code! The
title could be wxStaticText. The close button could
be a wxBitmapButton. Use your sizers to place these
and make life easier.

Actually, that’s the point of this exercise. :slight_smile: This isn’t production code… its ‘… I should learn some more edges of wxPython that I’ve never had a need to delve into before’. I have a toy-project I do some experimental stuff in just for the fun of it to learn stuff I’ve never had a need to do before.

(Besides, the title originally was going to be a StaticText – but I decided I wanted a shadow :))

Thanks, that solves those.

–S