Fighting with wxScrolledWindow

507 views
Skip to first unread message

ardi

unread,
May 4, 2012, 6:14:32 PM5/4/12
to wx-users
First of all, my apologies for asking too many questions in the
mailing list, as well as my lag in replying some of my threads... I'm
with a tight deadline working to finish a project, and I just have
time for coding :-\

I'm now having problems with wxScrolledWindow that has child controls.
I'm finding confusing behaviour in the children positions and sizes.
What I need is some kind of scrollable wxPanel which behaves _exactly_
as a non-scrolling one. I mean: children shouldn't be contaminated
with scrolled coordinates nor positions... the scrolling should be
hidden and transparent.

In other words, I want to create child controls on a wxPanel which
happens to be a wxScrolledWindow. But if I prefer to put the wxPanel
in a dialog instead of a wxScrolledWindow, the same code should work
(the only change needed should be to make the wxPanel a child of a
dialog).

I thought that adding a wxPanel as a child of a wxScrolledWindow, and
then putting the controls as children of the wxPanel instead of the
wxScrolledWindow would behave just like I wish, but that's not the
case... I'm still getting confused with positions and sizes with this
approach.

What would be the simplest way of doing what I want?

TIA

ardi

Vadim Zeitlin

unread,
May 4, 2012, 6:23:24 PM5/4/12
to wx-u...@googlegroups.com
On Fri, 4 May 2012 15:14:32 -0700 (PDT) ardi wrote:

a> In other words, I want to create child controls on a wxPanel which
a> happens to be a wxScrolledWindow. But if I prefer to put the wxPanel
a> in a dialog instead of a wxScrolledWindow, the same code should work
a> (the only change needed should be to make the wxPanel a child of a
a> dialog).

I don't understand this. wxScrolledWindow -- which is actually a
wxScrolled<wxPanel> and so is already a wxPanel -- *replaces* the panel.
You don't need both.

a> What would be the simplest way of doing what I want?

Use wxScrolledWindow instead of wxPanel and just call SetScrollRate() to
let it know that it should use the scrollbars. That's all.

Regards,
VZ

--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/

ardi

unread,
May 4, 2012, 6:40:55 PM5/4/12
to wx-users


On May 5, 12:23 am, Vadim Zeitlin <va...@wxwidgets.org> wrote:
> On Fri, 4 May 2012 15:14:32 -0700 (PDT) ardi wrote:
>
> a> In other words, I want to create child controls on a wxPanel which
> a> happens to be a wxScrolledWindow. But if I prefer to put the wxPanel
> a> in a dialog instead of a wxScrolledWindow, the same code should work
> a> (the only change needed should be to make the wxPanel a child of a
> a> dialog).
>
>  I don't understand this. wxScrolledWindow -- which is actually a
> wxScrolled<wxPanel> and so is already a wxPanel -- *replaces* the panel.
> You don't need both.

Not exactly, because the size of this "special" wxPanel is always the
size of the ScrolledWindow, but I need it to be the size of the real,
large, wxPanel. Yes, I know, that's the SetVirtualSize(), but this
VirtualSize thing is confusing me enormously, because the placement
and size of my child controls depend on the size of the wxPanel, and
so I can't use the standard GetSize() and SetSize() calls. Instead I
need to go the VirtualSize path, and even then, I didn't manage it to
work.

In other words, imagine I've a 500x500 wxScrolledWindow driving a
1000x1000 wxPanel. I need that child controls have no idea of the
500x500 scroll area. They should just know that they belong to a
1000x1000 wxPanel, and all their positions, sizes, etc should be
unaware of the 500x500 area... that 500x500 area shouldn't exist for
them.

Thanks a lot,

ardi

Eric Jensen

unread,
May 4, 2012, 8:30:03 PM5/4/12
to ardi
Hello ardi,

Saturday, May 5, 2012, 12:40:55 AM, you wrote:

a> Not exactly, because the size of this "special" wxPanel is always the
a> size of the ScrolledWindow, but I need it to be the size of the real,
a> large, wxPanel. Yes, I know, that's the SetVirtualSize(), but this
a> VirtualSize thing is confusing me enormously, because the placement
a> and size of my child controls depend on the size of the wxPanel, and
a> so I can't use the standard GetSize() and SetSize() calls. Instead I
a> need to go the VirtualSize path, and even then, I didn't manage it to
a> work.

a> In other words, imagine I've a 500x500 wxScrolledWindow driving a
a> 1000x1000 wxPanel. I need that child controls have no idea of the
a> 500x500 scroll area. They should just know that they belong to a
a> 1000x1000 wxPanel, and all their positions, sizes, etc should be
a> unaware of the 500x500 area... that 500x500 area shouldn't exist for
a> them.

You're overcomplicating things, in this scenario you don't have to
worry about the virtual vs visual size at all.

Take the "minimal" sample and add these few lines at the end of the
MyFrame ctor.

If the frame is too small to display the 16 buttons, you'll see
scrollbars. If not, it'll look just like a wxPanel.

HTH
Eric


---
wxScrolledWindow *panel = new wxScrolledWindow(this, wxID_ANY);

wxSizer *sizer = new wxBoxSizer(wxVERTICAL);
for(int i=0; i<16; i++) {
wxString label;
label << "Button " << i;
sizer->Add( new wxButton(panel, wxID_ANY, label), 0, wxALL, 4 );
}
panel->SetScrollRate(10,10);
panel->SetSizer(sizer);
panel->SetAutoLayout(true);
---

Gadget/Steve

unread,
May 5, 2012, 2:21:39 AM5/5/12
to wx-u...@googlegroups.com
Ardi,

I suspect that the root of your problems are that you are not using
sizers but are trying to position all your controls with absolute
co-ordinates - if you were using sizers then you would not need your
controls to know anything about the window/panel sizes and coordinates
regardless of what they were. Seriously consider refactoring your code
so that all the controls have a position wx.DefaultPosition and are laid
out by sizers - you will find that once you get the hang of them that
your code becomes enormously more maintainable and a lot of things just
start to work for you including scrolling and resizing.

Gadget/Steve

ardi

unread,
May 5, 2012, 3:23:32 AM5/5/12
to wx-users


On May 5, 8:21 am, Gadget/Steve <GadgetSt...@live.co.uk> wrote:
>[...]
> I suspect that the root of your problems are that you are not using
> sizers but are trying to position all your controls with absolute
> co-ordinates - if you were using sizers then you would not need your
> controls to know anything about the window/panel sizes and coordinates
> regardless of what they were.  Seriously consider refactoring your code
> so that all the controls have a position wx.DefaultPosition and are laid
> out by sizers - you will find that once you get the hang of them that
> your code becomes enormously more maintainable and a lot of things just
> start to work for you including scrolling and resizing.

Yes, Steve, my problem is exactly like you described. Unfortunately,
my task in this moment is writing a layer that sits between wxWidgets
and a portable application (based on a custom API). Such custom API
positions controls as percent-ratio coordinates of parents, just like
the deprecated constraints did.

Before you say it's an impossible task, let me say that it's almost
finished in this moment. All controls work fine, my intermediate layer
is working fine, and the layout of the application works fine...
except... scrolledwindows. The ScrolledWindow is the _only_ control
whose layout fails.

Yes, percent-ratio position of childs isn't a good practice nowadays,
and that custom API will change in a future version to choose another
positioning mechanism. But, for the moment, this portable application
needs to work as-is before this Tuesday. As I said, I'm almost there,
I just need to make the ScrolledWindow work.

Maybe my question could be formulated like this: Is there some class I
can use between a wxScrolledWindow and its childs, so that childs
positions and sizes can be explicitly set, and so that such positions
and sizes would have the same values if there was no scrolled window
and, for example the panel was on a dialog?

Thanks a lot!

ardi


Gadget/Steve

unread,
May 5, 2012, 4:45:20 AM5/5/12
to wx-u...@googlegroups.com
Ardi,

A quick question is does your layout work if the display is in a
scrolled window that is not a dialogue? If it does then simply make the
window behave as if it is a dialogue without inheriting from wxDialog -
i.e. show it when needed, give it Ok & Cancel buttons and hide it as
part of the button handlers.

Looking back at your original post it looks as if your problem could be
resolved by simply replacing all your GetSize calls with GetVirtualSize
- if your 1000x1000 panel is shown directly then this will be equivalent
to GetSize but if it is in a wxScrolledWindow then it will return the
1000x1000 set by the SetVirtualSize and everything should just work.

Steve

Vadim Zeitlin

unread,
May 5, 2012, 7:10:29 AM5/5/12
to wx-u...@googlegroups.com
On Sat, 5 May 2012 00:23:32 -0700 (PDT) ardi wrote:

a> On May 5, 8:21 am, Gadget/Steve <GadgetSt...@live.co.uk> wrote:
a> >[...]
a> > I suspect that the root of your problems are that you are not using
a> > sizers but are trying to position all your controls with absolute
a> > co-ordinates
...
a> Yes, Steve, my problem is exactly like you described.

OK, then forget my initial advice, it indeed only works with automatic
layout.

a> Before you say it's an impossible task

Of course it's not impossible, it's just not as trivial as making it work
using sizers.

a> Maybe my question could be formulated like this: Is there some class I
a> can use between a wxScrolledWindow and its childs, so that childs
a> positions and sizes can be explicitly set, and so that such positions
a> and sizes would have the same values if there was no scrolled window
a> and, for example the panel was on a dialog?

If you have a panel as a child of wxScrolledWindow this is exactly what
should happen.

OTOH I'd still avoid using nested windows unnecessarily and would just
apply wxScrolledWindow::CalcUnscrolledPosition() to get the logical
coordinates from the physical ones (or CalcScrolledPosition() to go in the
other sense). If you manage all the coordinates on your own it should be
simple enough to add these calls where necessary.

ardi

unread,
May 7, 2012, 6:17:07 AM5/7/12
to wx-users

On May 5, 1:10 pm, Vadim Zeitlin <va...@wxwidgets.org> wrote:
> On Sat, 5 May 2012 00:23:32 -0700 (PDT) ardi wrote:
>
> a> On May 5, 8:21 am, Gadget/Steve <GadgetSt...@live.co.uk> wrote:
> a> >[...]
> a> > I suspect that the root of your problems are that you are not using
> a> > sizers but are trying to position all your controls with absolute
> a> > co-ordinates
> ...
> a> Yes, Steve, my problem is exactly like you described.
>
>  OK, then forget my initial advice, it indeed only works with automatic
> layout.
>
> a> Before you say it's an impossible task
>
>  Of course it's not impossible, it's just not as trivial as making it work
> using sizers.

Thanks a lot for all your comments. I finally got it working with an
extra wxPanel. I agree it's not the best solution, but I need it to
work now, and this makes it, although I'll implement it better in a
future version.

Thanks!!

ardi
Reply all
Reply to author
Forward
0 new messages