wxSplitterWindow - How to set initial position of the sash?

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
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 298
Joined: Tue Oct 20, 2020 3:35 pm

wxSplitterWindow - How to set initial position of the sash?

Post by apoorv569 » Sun Jun 20, 2021 8:36 am

I have 2 wxSplitterWindow in my app, defined like this this,

Code: Select all

    // Main panel of the app
    m_MainPanel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);

    // Creating top splitter window
    m_TopSplitter = new wxSplitterWindow(m_MainPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_BORDER | wxSP_LIVE_UPDATE);
    m_TopSplitter->SetMinimumPaneSize(200);
    m_TopSplitter->SetSashGravity(0);

    // Top half of TopSplitter window
    m_TopPanel = new wxPanel(m_TopSplitter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);

    // Bottom half of the TopSplitter window
    m_BottomSplitter = new wxSplitterWindow(m_TopSplitter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_BORDER | wxSP_LIVE_UPDATE);
    m_BottomSplitter->SetMinimumPaneSize(300);
    m_BottomSplitter->SetSashGravity(0.2);
.
.
.
    // Set split direction
    m_TopSplitter->SplitHorizontally(m_TopPanel, m_BottomSplitter);
    m_BottomSplitter->SplitVertically(m_BottomLeftPanel, m_BottomRightPanel);
Image

These are the 2 splitter window in photo above, I set the SashGravity(), but for some reason both splitters always open in middle of the application. I tried multiple values, from 0-0.1, to 0.9-1. I also tried setting the position manually by calling SetSashPosition() but it does not seem to work either. I want to always open the splitters sash on their minimum set size, i.e 200 for the top splitter and 300 for the bottom splitter.

Also the flag wxSP_BORDER, wxSP_NOBORDER, wxSP_3DBORDER, wxSP_3D no matter I use they all look same, I can't see a difference. I wanted to use wxSP_THIN_SASH as I want the splitter, the drag-able space to be thin.

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

Re: wxSplitterWindow - How to set initial position of the sash?

Post by doublemax » Sun Jun 20, 2021 9:29 am

Did you call SetSashPosition() after the Split* call? (Or pass it as third parameter to it)
Use the source, Luke!

apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 298
Joined: Tue Oct 20, 2020 3:35 pm

Re: wxSplitterWindow - How to set initial position of the sash?

Post by apoorv569 » Sun Jun 20, 2021 10:32 am

doublemax wrote:
Sun Jun 20, 2021 9:29 am
Did you call SetSashPosition() after the Split* call? (Or pass it as third parameter to it)
I called it after creating the widget, like this,

Code: Select all

    // Creating top splitter window
    m_TopSplitter = new wxSplitterWindow(m_MainPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_THIN_SASH | wxSP_LIVE_UPDATE);
    m_TopSplitter->SetMinimumPaneSize(200);
    m_TopSplitter->SetSashGravity(0);
    m_TopSplitter->SetSashPosition(5);
I used the value 5 here as an example.

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

Re: wxSplitterWindow - How to set initial position of the sash?

Post by doublemax » Sun Jun 20, 2021 10:54 am

My question implied that you should call SetSashPosition after the Split() call, i.e. after the windows have been assigned to it. Sorry if that wasn't clear.
Use the source, Luke!

apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 298
Joined: Tue Oct 20, 2020 3:35 pm

Re: wxSplitterWindow - How to set initial position of the sash?

Post by apoorv569 » Sun Jun 20, 2021 11:15 am

doublemax wrote:
Sun Jun 20, 2021 10:54 am
My question implied that you should call SetSashPosition after the Split() call, i.e. after the windows have been assigned to it. Sorry if that wasn't clear.
Okay, it seems to be working,

Code: Select all

    // Set split direction
    m_TopSplitter->SplitHorizontally(m_TopPanel, m_BottomSplitter);
    m_BottomSplitter->SplitVertically(m_BottomLeftPanel, m_BottomRightPanel);

    m_TopSplitter->SetSashPosition(300);
    m_BottomSplitter->SetSashPosition(450);
However, I cannot understand, no matter what value I set here now, they don't seem to move, the top splitter is always shown on minimum sash size, no matter if I set the value to 1 or 500, the bottom splitter shows a little to the left now, not on its minimum size though. How are the values here defined? according to the sash size?

Also just curious, is it because I was trying to call SetSashPosition() before Split(), it was resetting/repositioning it somehow?

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

Re: wxSplitterWindow - How to set initial position of the sash?

Post by doublemax » Sun Jun 20, 2021 12:35 pm

apoorv569 wrote:
Sun Jun 20, 2021 11:15 am
Also just curious, is it because I was trying to call SetSashPosition() before Split(), it was resetting/repositioning it somehow?
SetSashPosition() just does nothing if there are no windows assigned yet.

This one is just a guess, try changing the order of calls:

Code: Select all

m_TopSplitter->SplitHorizontally(m_TopPanel, m_BottomSplitter);
m_TopSplitter->SetSashPosition(300);

m_BottomSplitter->SplitVertically(m_BottomLeftPanel, m_BottomRightPanel);
m_BottomSplitter->SetSashPosition(450);
Use the source, Luke!

apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 298
Joined: Tue Oct 20, 2020 3:35 pm

Re: wxSplitterWindow - How to set initial position of the sash?

Post by apoorv569 » Sun Jun 20, 2021 12:50 pm

doublemax wrote: SetSashPosition() just does nothing if there are no windows assigned yet.
I see.
doublemax wrote: This one is just a guess, try changing the order of calls:

Code: Select all

m_TopSplitter->SplitHorizontally(m_TopPanel, m_BottomSplitter);
m_TopSplitter->SetSashPosition(300);

m_BottomSplitter->SplitVertically(m_BottomLeftPanel, m_BottomRightPanel);
m_BottomSplitter->SetSashPosition(450);
I tried changing the order, still the same. The bottom splitter does not want to go to its minimum size i.e 300.

DavidHart
Site Admin
Site Admin
Posts: 4063
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Re: wxSplitterWindow - How to set initial position of the sash?

Post by DavidHart » Sun Jun 20, 2021 2:07 pm

Hi,

At least in wxGTK, I've found that trying to set a sash position before the TLW is shown usually fails. That's probably because, at that stage, the TLW has a size of 20,20 px. You can test if this is your problem by setting the position/gravity/whatever in an event handler that gets called later; if it works correctly from there, that's your problem.

In the past I caught wxEVT_IDLE and tested that the TLW had a sane size; if so, I set the position/gravity and Disconnect()ed the event. Nowadays I'd probably do something similar using CallAfter().

Regards,

David

apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 298
Joined: Tue Oct 20, 2020 3:35 pm

Re: wxSplitterWindow - How to set initial position of the sash?

Post by apoorv569 » Sun Jun 20, 2021 2:19 pm

DavidHart wrote:
Sun Jun 20, 2021 2:07 pm
Hi,

At least in wxGTK, I've found that trying to set a sash position before the TLW is shown usually fails. That's probably because, at that stage, the TLW has a size of 20,20 px. You can test if this is your problem by setting the position/gravity/whatever in an event handler that gets called later; if it works correctly from there, that's your problem.

In the past I caught wxEVT_IDLE and tested that the TLW had a sane size; if so, I set the position/gravity and Disconnect()ed the event. Nowadays I'd probably do something similar using CallAfter().

Regards,

David
Sorry, but I don't know what TLW is? Do you mean Top level window?

DavidHart
Site Admin
Site Admin
Posts: 4063
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Re: wxSplitterWindow - How to set initial position of the sash?

Post by DavidHart » Sun Jun 20, 2021 4:26 pm

Yes.

apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 298
Joined: Tue Oct 20, 2020 3:35 pm

Re: wxSplitterWindow - How to set initial position of the sash?

Post by apoorv569 » Mon Jun 21, 2021 10:04 am

DavidHart wrote:
Sun Jun 20, 2021 2:07 pm
Hi,

At least in wxGTK, I've found that trying to set a sash position before the TLW is shown usually fails. That's probably because, at that stage, the TLW has a size of 20,20 px. You can test if this is your problem by setting the position/gravity/whatever in an event handler that gets called later; if it works correctly from there, that's your problem.

In the past I caught wxEVT_IDLE and tested that the TLW had a sane size; if so, I set the position/gravity and Disconnect()ed the event. Nowadays I'd probably do something similar using CallAfter().

Regards,

David
I am not really sure how to use CallAfter(), but I tried doing this way, in the end of constructor of my MainFrame class which inherits from wxFrame, I added this line,

Code: Select all

MainFrame::MainFrame()
    : wxFrame(NULL, wxID_ANY, "Sample Hive", wxDefaultPosition),
      m_ConfigFilepath("config.yaml"), m_DatabaseFilepath("sample.hive")
{
.
.
.
    CallAfter(&MainFrame::LoadStuff);
}
and the function definition is,

Code: Select all

void MainFrame::LoadStuff()
{
    wxLogDebug("SASH BEFORE - T: %d B: %d", m_TopSplitter->GetSashPosition(), m_BottomSplitter->GetSashPosition());

    m_TopSplitter->SetSashPosition(210);
    m_BottomSplitter->SetSashPosition(800);

    wxLogDebug("SASH AFTER - T: %d B: %d", m_TopSplitter->GetSashPosition(), m_BottomSplitter->GetSashPosition());
}
This looks like it is working, though the print statements both before and after prints the same value for some reason,

Code: Select all

15:30:17: Debug: SASH BEFORE - T: 200 B: 300
15:30:17: Debug: SASH AFTER - T: 200 B: 300
I also had to set both splitter window sash gravity to 0, to make the above code work,

Code: Select all

    // Creating top splitter window
    m_TopSplitter = new wxSplitterWindow(m_MainPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_NOBORDER | wxSP_THIN_SASH | wxSP_LIVE_UPDATE);
    m_TopSplitter->SetMinimumPaneSize(200);
    m_TopSplitter->SetSashGravity(0);

    // Bottom half of the TopSsplitter window
    m_BottomSplitter = new wxSplitterWindow(m_TopSplitter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_NOBORDER | wxSP_THIN_SASH | wxSP_LIVE_UPDATE);
    m_BottomSplitter->SetMinimumPaneSize(300);
    m_BottomSplitter->SetSashGravity(0);
 
Is this the correct way to do this?

DavidHart
Site Admin
Site Admin
Posts: 4063
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Re: wxSplitterWindow - How to set initial position of the sash?

Post by DavidHart » Mon Jun 21, 2021 10:40 am

This looks like it is working
'looks like', or 'is'?
Is this the correct way to do this?
If it is working...
I also had to set both splitter window sash gravity to 0, to make the above code work,
What goes wrong if you don't set it to zero?

More generally:
1) Have you tried the 'splitter' sample? If you built wxWidgets yourself, it's in /path/to/build-dir/samples/. If you use the distro version, the samples may be supplied, perhaps in a separate package; for debian and derivatives that's wx3.0-examples or similar, and installs to /usr/share/doc/wx-examples/ or /usr/share/doc/wx3.0-examples/ or...

2) If your code still isn't working correctly, it's always a good idea, both for your own use and to post here, to create a minimal compilable sample that demonstrates the problem. The best way to do that is usually to alter one of those wx samples; often 'minimal', but in your case 'splitter' might be better.

apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 298
Joined: Tue Oct 20, 2020 3:35 pm

Re: wxSplitterWindow - How to set initial position of the sash?

Post by apoorv569 » Mon Jun 21, 2021 11:07 am

'looks like', or 'is'?
I said looks like because I was not a 100% sure, and because of the print statements also. Just want to make sure that it will be stable and won't give me any problems in future.
What goes wrong if you don't set it to zero?
The sash for the bottom splitter showed at position slightly greater, like instead of 300 it was 350 or something. As I had the gravity for the bottom splitter at 0.2
More generally:
1) Have you tried the 'splitter' sample? If you built wxWidgets yourself, it's in /path/to/build-dir/samples/. If you use the distro version, the samples may be supplied, perhaps in a separate package; for debian and derivatives that's wx3.0-examples or similar, and installs to /usr/share/doc/wx-examples/ or /usr/share/doc/wx3.0-examples/ or...

2) If your code still isn't working correctly, it's always a good idea, both for your own use and to post here, to create a minimal compilable sample that demonstrates the problem. The best way to do that is usually to alter one of those wx samples; often 'minimal', but in your case 'splitter' might be better.
I did try the sample, but not recently. I will take another look.

I'm on ArchLinux, not sure if Arch provided samples, could be in the AUR. But I do have built wxWidgets myself but, for building my own app I use the distribution version though.

Post Reply