Well, I think I got somewhere… this would be the modified
MainComponent.cpp (in respect to the gist code):
setSize (600, 400);
void MainContentComponent::paint (Graphics& g)
//~ g.fillAll (Colour (0xff001F36));
g.fillAll (Colour (0xff888888));
g.setFont (Font (16.0f));
g.drawText ("Hello World!", getLocalBounds(), Justification::centred, true);
// This is called when the MainContentComponent is resized.
// If you add any child components, this is where you should
// update their positions.
myGSliders.setSize(getWidth()-0, myGSliders.getHeight()); // needs some space for v.scrollbar
myViewport.setBounds(0, 0, proportionOfWidth(1.0f), 76); // but first size the view
myGSliders.setSize(myViewport.getMaximumVisibleWidth(), myGSliders.getHeight()); // then resize component again, leaving space for scrollbar
The problem with the exception at exit is actually discussed in Access violation on closing Window when using Viewport - the problem is a double free; note that in
myGSliders properties are declared as objects:
class MainContentComponent : public Component
void paint (Graphics&) override;
void resized() override;
This crudely means that “C++” will take of their destruction, we do not have to manually delete them. However, the
.setViewedComponent method has a
deleteComponentWhenNoLongerNeeded argument which is by default
true, and as such it will attempt to delete the viewed component at application exit, even if it has been already deleted. To prevent that, one must explicitly set
false and then the unmap exception disappears.
As far as the sizing goes, first, I noticed that unless I call
resized() in the constructor, something was weird with the scrollbars at very first display (i.e. I got horizontal instead of vertical scrollbar); then after a window resize, this is corrected. (something similar is mentioned in How to Use a Viewport)
Then, in the
resized() menthod, I have to change the sizes of both
myGSliders needs to be resized twice. First, I do:
In principle, I just need to set the width of
myGSliders, not its height - however, there is no SetWidth method of JUCE Component, so I must do a
getWidth(), which would get the size of the parent (the window), and setting the height to the current height of
myGSliders so it doesn’t change.
myGSliders sized, I can size the Viewport:
myViewport.setBounds(0, 0, proportionOfWidth(1.0f), 76);
… noting that instead of using
.setBoundsRelative, which forces me to use relative percentages for all parameters, I use
.setBounds which forces me to use pixels - however, there is a
proportionOfWidth function which accepts a float/percent, and returns pixels (In respect to parent width, I guess).
Since now the total size of the viewport is set, we can now use the
.getMaximumVisibleWidth method to find out (implicitly) what is the width of the vertical scrollbar that needs to be taken into account - or rather, what is the remaining width of the viewport - and set the
myGSliders width to it:
myGSliders is set at the width of the window, and since the vertical scrollbar is also shown (taking up a bit of the window), the engine thinks that a portion is missing, and insists on showing a horizontal scrollbar (while the vertical does not have its thumb element rendered).
And finally, the layout is as intended:
… and it scales with window resize (inner sliders too).