When to SetSashPosition of splitter ?

hello,

I've trouble setting the initial sash position of a splitter over different platforms.

If I make a simple aplication, in which I set the SashPosition at the end of the form's init,
everything works on "every" platform ( Windows, Ubuntu, Fedora )

Now when I make a larger application,
setting the SashPosition at the end of the init of the mainform, results in the following results:
Windows: Ok
Fedora: Sash not set
Ububtu: Sash not set

Using wx.CallAfter at the end of the init, results remain the same.

Using wx.CallLater at the end of the init:
    wx.CallLater ( 100, self.Split_V2.SetSashPosition, -205 )
    wx.CallLater ( 100, self.Split_Demo.SetSashPosition, 150 )

works on all 3 systems.

Can anyone explain what's happening here ?
And moreover what delay should I use, to safely let my application work on all systems ?
Or are there better solutions ?

thanks,
Stef Mientki

Stef Mientki wrote:

hello,

I've trouble setting the initial sash position of a splitter over different platforms.

If I make a simple aplication, in which I set the SashPosition at the end of the form's init,
everything works on "every" platform ( Windows, Ubuntu, Fedora )

Now when I make a larger application,
setting the SashPosition at the end of the init of the mainform, results in the following results:
Windows: Ok
Fedora: Sash not set
Ububtu: Sash not set

Using wx.CallAfter at the end of the init, results remain the same.

Using wx.CallLater at the end of the init:
   wx.CallLater ( 100, self.Split_V2.SetSashPosition, -205 )
   wx.CallLater ( 100, self.Split_Demo.SetSashPosition, 150 )

works on all 3 systems.

Can anyone explain what's happening here ?

The splitter window has code that will ensure that the requested sash position is within range of the current size of the window. However since the default size is something like 20,20 and since it will typically not be resized to the final initial size until sometime after it and its parents have been created (such as in the first EVT_SIZE event when the sizer is evaluated) then setting an initial sash position > 20 would always fail and the value would be clamped into the 0-20 range. To work around this common problem the splitter window also has code that tries to be smart and wait to set that initial sash position until after the first EVT_SIZE event. Most of the time that works fine. However if there is more than one EVT_SIZE happening before the final size is reached then this workaround can fail. One example where I've seen this fail is if the parent panel is Fit()ed and then the frame is shown and the parent panel is sized again to fit the frame and that causes the splitter to be sized larger than it was with the first Fit.

And moreover what delay should I use, to safely let my application work on all systems ?
Or are there better solutions ?

The best thing to do is to just ensure that there is no more than one EVT_SIZE between the time you set the sash position (or pass a sash position to one of the Split* methods) and the time that the final initial size of the window is set. This can usually be accomplished by ensuring that there is nothing that would set the size of the splitter or its parents, other than setting the initial size of the frame.

If that's not possible then the safest thing to do would be to find a way to wait until all the initial size events have been processed. Usually 100 ms should be enough but there could be situations when it is not. So something that you might consider is to start the timer in the EVT_SIZE event, and then reset the timer in the next EVT_SIZE if it hasn't expired already. Then as soon as there isn't any EVT_SIZE event for X ms you can set the initial sash position and not set the timer any more.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Robin Dunn wrote:

Stef Mientki wrote:

hello,

I've trouble setting the initial sash position of a splitter over different platforms.

If I make a simple aplication, in which I set the SashPosition at the end of the form's init,
everything works on "every" platform ( Windows, Ubuntu, Fedora )

Now when I make a larger application,
setting the SashPosition at the end of the init of the mainform, results in the following results:
Windows: Ok
Fedora: Sash not set
Ububtu: Sash not set

Using wx.CallAfter at the end of the init, results remain the same.

Using wx.CallLater at the end of the init:
   wx.CallLater ( 100, self.Split_V2.SetSashPosition, -205 )
   wx.CallLater ( 100, self.Split_Demo.SetSashPosition, 150 )

works on all 3 systems.

Can anyone explain what's happening here ?

The splitter window has code that will ensure that the requested sash position is within range of the current size of the window. However since the default size is something like 20,20 and since it will typically not be resized to the final initial size until sometime after it and its parents have been created (such as in the first EVT_SIZE event when the sizer is evaluated) then setting an initial sash position > 20 would always fail and the value would be clamped into the 0-20 range. To work around this common problem the splitter window also has code that tries to be smart and wait to set that initial sash position until after the first EVT_SIZE event. Most of the time that works fine. However if there is more than one EVT_SIZE happening before the final size is reached then this workaround can fail. One example where I've seen this fail is if the parent panel is Fit()ed and then the frame is shown and the parent panel is sized again to fit the frame and that causes the splitter to be sized larger than it was with the first Fit.

And moreover what delay should I use, to safely let my application work on all systems ?
Or are there better solutions ?

The best thing to do is to just ensure that there is no more than one EVT_SIZE between the time you set the sash position (or pass a sash position to one of the Split* methods) and the time that the final initial size of the window is set. This can usually be accomplished by ensuring that there is nothing that would set the size of the splitter or its parents, other than setting the initial size of the frame.

If that's not possible then the safest thing to do would be to find a way to wait until all the initial size events have been processed. Usually 100 ms should be enough but there could be situations when it is not. So something that you might consider is to start the timer in the EVT_SIZE event, and then reset the timer in the next EVT_SIZE if it hasn't expired already. Then as soon as there isn't any EVT_SIZE event for X ms you can set the initial sash position and not set the timer any more.

thanks Robin,

as starting my program takes between 5 and 10 seconds,
I don't mind adding an extra 0.5 seconds :wink:

cheers,
Stef