Basic of dynamic component creation


#1

I’m new to juce, and a bit rusty with c++. I’ve got the sample apps in the extras folder running, but soon after I tried a component created with The Jucer - I got a leaked object detected. Nice feature to have by the way, to notify rusty programmers that they have gotten sloppy.

What did I forget to do? I created a textButton with addAndMakeVisible in my component’s creator, and the destructor calls deleteAndZero.

Eventually, my idea is to have an array of pointers to the dynamic objects I’m creating, to “free” them in the destructor.
I’m hoping to line these objects up in rows and resize them as their parent window resizes.

I know this is some basic stuff, but any suggestions would be helpfull. Including a referance to any juce related tutorial, or a sample application.


#2

Post the code, and we’ll give ya hand! :slight_smile:


#3

This old dog ain’t gone yet!

In the process of “cleaning” up the code to post it, I saw some faulty code in the parent component. Turns out it’s fairly straightforward to make dynamic components, at least so far.

Very nice that memory leaks are reported, notifying which object is doing it.

I’m sure I’ll have another simple question before too long.

Thanks for the offer!


#4

Welcome !
You should take the habit of using RAII-pointers however, like ScopedPointer, instead of “deleteAndZero”, they remove a lot of the memory management headaches and are exception safe ! :smiley:


#5

I’d also look into the OwnedArray class, especially if you need to keep track of all those objects.


#6

OK, I’m going to have to read up on this stuff.

So far I was just doing a “proof of concept” build, but I did use addAndMakeVisible upon creation as well as deleteAllChildren in the
destructor. Is this just a case of there being a couple of ways of accomplishing the same thing - Or is there a difference?


#7

http://ootips.org/yonat/4dev/smart-pointers.html#Why :wink:


#8

Fair warning (this applies to all who try to help C++ newcomers): you can post all sorts of links related to RAII to help, but it may not be obvious to someone like gordcoder how that can solve his initial problem. Get the basics straight, then move to things like RAII.


#9

You’re absolutely right, but the OP already managed to solve his problem. I was just trying to elaborate on something which is considered as a best-practice, because he seemed to have understood the basics :slight_smile:


#10

C++ newbie here, having trouble dynamically creating components.

I'm making a MIDI plugin with a 2D grid that has balls bouncing around in it. 

Here's an example of what I'm trying to build:

http://www.earslap.com/page/otomata.html

I need to rotate each individual ball's graphic periodically, based on its direction of travel. But I also need to dynamically create new balls when you click on a grid cell - potentially allowing a HUGE number of balls bouncing around.

I just can't figure out how to dynamically create Ball components and make them visible. Do I just make a Ball class that inherits Component, and then create a std::vector<Ball> vector of Balls in my MainContentComponent? And then dynamically push_back new Balls as they're created? When/where/how do I go about using addAndMakeVisible on each Ball, and removing it when it gets destroyed by the user?

I've looked at this tutorial:

http://www.juce.com/doc/tutorial_component_parents_children

But can't deduce from that how to dynamically create/addAndMakeVisible new components from it.


#11

Okay, I figured out how to modify the "Components - Parents & Children" Xcode project to dynamically create components on click, using a vector of ScopedPointers in the MainComponent class:

private:
    std::vector< ScopedPointer< SunComponent > > suns;

And then this, to dynamically create a component on click (using mouseDown):

SunComponent* sun = new SunComponent();
suns.push_back(sun);
addAndMakeVisible(sun);
sun->setBounds(e.x - 25, e.y - 25, 50, 50);

However, when I try to bring the exact same code into the plugin I'm working on, I get the following build error:

new_allocator.h -> Call to deleted constructor of 'juce::ScopedPointer<SunComponent>'
vector.tcc      -> Call to deleted constructor of 'juce::ScopedPointer<SunComponent>'

Any idea why I'm getting this error? Wondering if it's a C++11 issue or something. I started making this plugin a year or two ago in Juce 3.x... is that the problem? Should I start a new Jucer project and import the code in? I tried comparing build settings between my plugin and the "Components - Parents & Children" example project and couldn't find any major differences that would explain this error.


#12

So I built a new plugin using ProJucer 4.X and ported the code over, and now it's building properly without throwing that error. Must have been some compiler flag or something else I was missing, left over from the IntroJucer 3.X project.


#13

You shouldn't be using a std::vector< ScopedPointer< SunComponent > > suns; even if this compiles it will lead you into trouble. ScopedPointer is not meant to be used inside a container as it does not support copying, moving etc. in the way you would expect.

My advice: if you're on C++98, use a OwnedArray<SunComponent>, as this is the proper JUCE way to do such a thing; if you're on C++11/14, use a std::vector<std::unique_ptr<SunComponent>> which imho is the best way to do such a structure in the modern world.