wxScrolledWindow - scrollbar thumb position staying at the top always

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
deepti
Earned some good credits
Earned some good credits
Posts: 115
Joined: Tue Jul 17, 2018 5:38 pm

wxScrolledWindow - scrollbar thumb position staying at the top always

Post by deepti » Tue Jul 17, 2018 5:45 pm

Hi All,

I have a wxScrolledWindow instance, where I need to dynamically add controls. So, the size of the window changes dynamically. The vertical scrollbar appears, and when new controls are added to the wxScrolledWindow instance, the thumb size also changes. However, the thumb always remains at the top. I need the thumb to scroll to the position of newly added control.

I have these lines in the constructor of my dialog:

Code: Select all

	m_metaDataScrolledWindow = new wxScrolledWindow(m_panelNetworkFoldersSettings, 100, wxDefaultPosition, wxSize(-1, -1), 
                                                                                                                                                      wxBORDER_SIMPLE| wxVSCROLL);
	m_metaDataScrolledWindow->SetVirtualSize(1000, 1000);
	m_metaDataScrolledWindow->SetScrollRate(0, 16);
	m_metaDataScrolledWindow->Refresh();

        m_metaDataControlsbox = new wxBoxSizer(wxVERTICAL);
	m_metaDataScrolledWindow->SetSizer(m_metaDataControlsbox);
And, in the "Add" method which is called when the user clicks a button to add more controls, I have the following lines:

Code: Select all

	m_metaDataScrolledWindow->SetSizerAndFit(m_metaDataControlsbox);
	m_metaDataControlsbox->SetSizeHints(m_metaDataScrolledWindow);
	m_metaDataScrolledWindow->FitInside();
	m_metaDataControlsbox->FitInside(m_metaDataScrolledWindow);
	m_metaDataControlsbox->Layout();
	m_boxSizerMetadataPage->Layout();
	m_boxSizerOverallMain->Layout();
What is it that I am missing here in order to update the scrollbar thumb position? Please help!

Regards,
Deepti

User avatar
doublemax
Moderator
Moderator
Posts: 15074
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxScrolledWindow - scrollbar thumb position staying at the top always

Post by doublemax » Tue Jul 17, 2018 7:17 pm

What is it that I am missing here in order to update the scrollbar thumb position? Please help!
Which part of the code you posted do you expect to scroll the window to the bottom?

You could try to just Focus() one of the newly added controls. I think there is some code in wxWidgets that automatically scrolls this into view. But i'm not 100% sure about this.

If that doesn't work, you have to calculate the scroll position yourself.
Use the source, Luke!

deepti
Earned some good credits
Earned some good credits
Posts: 115
Joined: Tue Jul 17, 2018 5:38 pm

Re: wxScrolledWindow - scrollbar thumb position staying at the top always

Post by deepti » Wed Jul 18, 2018 6:21 am

@doublemax, thank you for your reply.

I need the scrollbar thumb position to be updated whenever an "Add" button is clicked, that is, when new controls are added to the wxScrolledWindow instance. Please note that the thumb size is getting updated. Only the position always stay at the top of the scrollbar. But I need it to be at the position of the last newly added control.
Could you please help me with how to calculate the scroll position?

Thanks in advance!

User avatar
doublemax
Moderator
Moderator
Posts: 15074
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxScrolledWindow - scrollbar thumb position staying at the top always

Post by doublemax » Wed Jul 18, 2018 7:50 am

First try calling Focus() on any of the newly added controls. This should scroll the control into view (i looked into the source code).

If you need to calculate the scroll position yourself, you need:

GetVirtualSize() - get virtual size of the window
GetClientSize() - get size of the visual portion of the window
GetScrollPixelsPerUnit() - needed because Scroll() takes scroll units, not pixels
Scroll() - performs the actual scrolling
Use the source, Luke!

deepti
Earned some good credits
Earned some good credits
Posts: 115
Joined: Tue Jul 17, 2018 5:38 pm

Re: wxScrolledWindow - scrollbar thumb position staying at the top always

Post by deepti » Thu Jul 19, 2018 6:42 am

Thank you for your reply @doublemax.
I have my own class "AGE_ScrolledWindow", derived from wxScrolledWindow. And have implemented the following in it's OnSize handler. With this, it is scrolling to the bottom whenever a new control is added.

void AGE_ScrolledWindow::OnSize(wxSizeEvent& Event)
{
wxScrolledWindow::HandleOnSize(Event);

int r = GetScrollLines(wxVERTICAL);

SetScrollPos(wxVERTICAL, r);
Scroll(0, r);

Refresh();
Update();
}

So far so good. But now, there is another issue I am facing. In the wxScrolledWindow, I am adding several instances of "wxCollapsiblePane". So when I expand/collapse any of these, the scrollbar should not hit the bottom of the wxScrolledWindow. Instead, it should show the currently selected wxCollapsiblePane instance.

However, what I do see is that if i open some other window (any random application), and then re-open my dialog box again, the view is correct. That is the repainting of window happens and then it shows the correct view (of the currently selected wxCollapsiblePane instance).
But, how can I achieve this repainting of the new scrolled position immediately (as soon as a wxCollapsiblePane instance is collapsed or expanded) ?

This is what I have written in handler for wxEVT_COLLAPSIBLEPANE_CHANGED event. But it is still not repainting immediately.

void PropertiesDialog::OnMetaDataControlExpand(wxCollapsiblePaneEvent& event)
{

wxCollapsiblePane* p = dynamic_cast<wxCollapsiblePane*>(event.GetEventObject());
p->SetFocus();
wxPoint pt = p->GetPosition();

m_metaDataScrolledWindow->Scroll(0, pt.y/16);
m_metaDataScrolledWindow->SetScrollPos(wxVERTICAL, pt.y/16);
wxClientDC dc(m_metaDataScrolledWindow);
m_metaDataScrolledWindow->DoPrepareDC(dc);

p->Refresh();
p->Update();
m_metaDataScrolledWindow->Refresh();
m_metaDataScrolledWindow->Update();
RefreshRect(m_metaDataScrolledWindow->GetClientRect());
Update();


m_metaDataScrolledWindow->FitInside();
m_metaDataControlsbox->FitInside(m_metaDataScrolledWindow);
m_metaDataScrolledWindow->Refresh();
m_metaDataControlsbox->SetSizeHints(m_metaDataScrolledWindow);
m_metaDataControlsbox->Layout();
}

Please help!

Post Reply