Page 1 of 1

Scrolling with SetTargetWindow (small layout issue)

Posted: Tue Dec 31, 2019 10:34 am
by bertolino
Hello all,

Starting from the scrolling code at https://wiki.wxwidgets.org/Scrolling (to which I've made as few changes as possible...), I wanted to test the use of SetTargetWindow. The final goal is to scroll a left panel with a right wxScrolledWindow (so don't pay attention to the right series of buttons).
That works pretty well but if you play enough with the frame size and the scrollbar and use a special combination of them, the layout of the left panel is bad (see the image below: whatever the scrollbar position, we should never have this empty space before the left series of buttons).
scrolled_window2.jpg
scrolled_window2.jpg (23.87 KiB) Viewed 663 times
The runnable code is here an below:
main.cpp
(2.02 KiB) Downloaded 67 times

Code: Select all

#include "wx/wx.h"
#include <iostream>

class ScrolledWidgetsPane : public wxScrolledWindow
{
public:
	ScrolledWidgetsPane(wxWindow* parent, wxWindowID id) : wxScrolledWindow(parent, id)
	{
		// the sizer will take care of determining the needed scroll size
		// (if you don't use sizers you will need to manually set the viewport size)
		wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);

		// add a series of widgets

		for (int w = 1; w <= 20; w++)
		{
			wxButton* b = new wxButton(this, wxID_ANY, wxString::Format(wxT("Button %i"), w));
			sizer->Add(b, 0, wxALL, 3);
		}
		
		this->SetSizer(sizer);

		// this part makes the scrollbars show up
		this->FitInside(); // ask the sizer about the needed size
		this->SetScrollRate(5, 5);
	}
};

class MyPane : public wxPanel
{
public:
	MyPane(wxWindow* parent, wxWindowID id) : wxPanel(parent, id)
	{
		// the sizer will take care of determining the needed scroll size
		// (if you don't use sizers you will need to manually set the viewport size)
		wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);

		// add a series of widgets
		for (int w = 1; w <= 20; w++)
		{
			wxButton* b = new wxButton(this, wxID_ANY, wxString::Format(wxT("Button %i"), w));
			sizer->Add(b, 0, wxALL, 3);
		}

		this->SetSizer(sizer);

		// this part makes the scrollbars show up
		this->FitInside(); // ask the sizer about the needed size
	}
};

// A sample app that adds the scrolled pane to a frame to make this code runnable
class MyApp : public wxApp
{
	wxFrame *frame;
public:

	bool OnInit()
	{
		wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
		frame = new wxFrame((wxFrame *)NULL, -1, wxT("Scrolling Widgets"), wxPoint(50, 50), wxSize(650, 650));

		MyPane* pane = new MyPane(frame, wxID_ANY);
		sizer->Add(pane, 1, wxEXPAND);

		ScrolledWidgetsPane* scroll = new ScrolledWidgetsPane(frame, wxID_ANY);
		sizer->Add(scroll, 1, wxEXPAND);
		scroll->SetTargetWindow(pane);

		frame->SetSizer(sizer);
		frame->Show();
		return true;
	}
};

IMPLEMENT_APP(MyApp)
Any help will be appreciated.
Have a good day and a great new year's eve!

Pascal

[Edit] To compare the layout issue with the normal scrolling behaviour, comment this line in the main:

Code: Select all

scroll->SetTargetWindow(pane);

Re: Scrolling with SetTargetWindow (small layout issue)

Posted: Thu Jan 02, 2020 1:47 am
by doublemax
I haven't tried the code yet, but i'm not sure a wxPanel is suitable for scrolling. Have you tried replacing it with a wxScrolledWindow without scrollbars?

Re: Scrolling with SetTargetWindow (small layout issue)

Posted: Thu Jan 02, 2020 11:39 am
by bertolino
Hello doublemax,

Thanks for your time and advice. I tried to do so but the behaviour is exactly the same.
Following your idea, I also noticed that if we have 2 scrolled windows (each one targeting the other, so we're supposed to be "full symmetric"), the behaviour of each one differs slightly from the other one which is a bit surprising.
The full code is below.

Have a good day,

Pascal

Code: Select all

#include "wx/wx.h"
#include <iostream>

class ScrolledWidgetsPane : public wxScrolledWindow
{
public:
	ScrolledWidgetsPane(wxWindow* parent, wxWindowID id) : wxScrolledWindow(parent, id)
	{
		// the sizer will take care of determining the needed scroll size
		// (if you don't use sizers you will need to manually set the viewport size)
		wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);

		// add a series of widgets
		for (int w = 1; w <= 20; w++)
		{
			wxButton* b = new wxButton(this, wxID_ANY, wxString::Format(wxT("Button %i"), w));
			sizer->Add(b, 0, wxALL, 3);
		}

		this->SetSizer(sizer);

		// this part makes the scrollbars show up
		this->FitInside(); // ask the sizer about the needed size
		this->SetScrollRate(5, 5);
	}
};

// A sample app that adds the scrolled pane to a frame to make this code runnable
class MyApp : public wxApp
{
	wxFrame *frame;
public:

	bool OnInit()
	{
		wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
		frame = new wxFrame((wxFrame *)NULL, -1, wxT("Scrolling Widgets"), wxPoint(50, 50), wxSize(650, 650));

		ScrolledWidgetsPane* pane1 = new ScrolledWidgetsPane(frame, wxID_ANY);
		sizer->Add(pane1, 1, wxEXPAND);
		ScrolledWidgetsPane* pane2 = new ScrolledWidgetsPane(frame, wxID_ANY);
		sizer->Add(pane2, 1, wxEXPAND);
		pane1->SetTargetWindow(pane2);		// comment these 2 lines
		pane2->SetTargetWindow(pane1);		// to see the difference
		frame->SetSizer(sizer);
		frame->Show();
		return true;
	}
};

IMPLEMENT_APP(MyApp)