Setting up an array of sliders/labels

Is it possible to create an array of juce::Sliders or juce::Labels such that I can perform operations via a loop as opposed to explicitly having to perform each step for each slider?

When I try to do Slider[6] arr = {slider1, slider2,... slidern}; I get the Call to deleted constructor of 'juce::Slider' error.

Use an OwnedArray

Rail

Currently, best practice is std::vector<std::unique_ptr<juce::Slider>>

Use juce::OwnedArray if you’re trying to work with legacy code.

The former has well-defined, standard move semantics, explicit ownership, and compatibility with STL algorithms and containers. The latter is a JUCE-specific legacy container with custom semantics & STL interoperability.

I would be no means call OwnedArray deprecated. It serves the same purpose as std::vector<std::unique_ptr<juce::Slider>> but offers way better user-friendly and more powerful operations.

1 Like

OwnedArray is also considerably less verbose.

I’d use std::vector<std::unique_ptr<>> if using STL algorithms or lots of non-JUCE code.

I generally recommend looking at the usage patterns of JUCE classes and finding free functions you can create to make common use cases less verbose.

For example:

template <typename T>
using CompVec = std::vector<std::unique_ptr<T>>;

template <typename T, typename... Args>
T& createComp(CompVec<T>& vec, Args&&... args)
{
    vec.emplace_back(std::make_unique<T>(std::forward<Args>(args)...));
    return *vec.back();
}

Then:

struct Comp: juce::Component
{
    Comp()
    {
        addAndMakeVisible(createComp(sliders));
    }

    CompVec<juce::Slider> sliders;
};

Now it’s trivial to create even less verbose versions of those, such as ones that automatically add the component to parent after creation, etc.

Nice, but I’m not sure I’d recommend that to a beginner who just wants to set up an array of sliders.

2 Likes
for (auto* component : { &slider1, &slider2, &slider3 })
    addAndMakeVisible(component);
2 Likes

Depending on the use case, you don’t have to use a separate container for Components since they are already contained by the parent Component. ie. you can iterate over the child components to locate the sliders, giving them explicit an type makes them easy to find.

1 Like

But a Component doesn’t own its children, so you do need an owning container if you want to avoid a memory leak, no?

1 Like

Correct. You need to free the memory in the parent store. I suspect one could write a little helper class that could automate the cleanup.

The helper is there already and the docs tell you not to use it!

1 Like