I am using the JUCE framework to create an audio plugin. I have created a Knob
class which inherits from the Component
class. My Knob
class contains references to a Slider
& a Label
.
In my AudioProcessorEditor
class, I initialize several Knob
objects. However, none of the Component
s are visible at run-time. Am I doing something wrong or missing a step?
I have tried declaring Slider
& Label
objects directly inside of my AudioProcessorEditor
class. When I do that, I am able to see the Slider
& Label
objects successfully at run-time. So I get the feeling that the issue involves my Knob
class.
#pragma once
#include "../JuceLibraryCode/JuceHeader.h"
class Knob : public Component
{
public:
Knob(String, AudioProcessorEditor*);
~Knob();
void paint (Graphics&) override;
void resized() override;
String Name;
Label *KnobLabel;
Slider *KnobSlider;
AudioProcessorEditor *APE;
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Knob)
};
#include "Knob.h"
Knob::Knob(String name, AudioProcessorEditor *ape)
{
// In your constructor, you should add any child components, and
// initialise any special settings that your component needs.
this->Name = name;
APE = ape;
KnobLabel = new Label(name);
KnobLabel->setColour(0x1000281, Colours::antiquewhite);
KnobLabel->setAlwaysOnTop(true);
KnobLabel->setFont(10);
KnobSlider = new Slider();
KnobSlider->setAlwaysOnTop(true);
addAndMakeVisible(KnobLabel);
addAndMakeVisible(KnobSlider);
}
void Knob::paint (Graphics& g)
{
/* This demo code just fills the component's background and
draws some placeholder text to get you started.
You should replace everything in this method with your own
drawing code..
*/
g.setColour(Colours::white);
g.fillAll();
}
void Knob::resized()
{
// This method is where you should set the bounds of any child
// components that your component contains..
auto bounds = getLocalBounds();
KnobSlider->setBounds(bounds.removeFromTop(getHeight()*8));
KnobLabel->setBounds(bounds);
}
#pragma once
#include "../JuceLibraryCode/JuceHeader.h"
#include "PluginProcessor.h"
#include "Knob.h"
#include "Model.h"
class MoonlightAudioProcessorEditor : public AudioProcessorEditor
{
public:
MoonlightAudioProcessorEditor (MoonlightAudioProcessor&);
~MoonlightAudioProcessorEditor();
void paint (Graphics&) override;
void resized() override;
Knob *OrbitKnob;
Knob *SpaceKnob;
Knob *InertiaKnob;
void ConfigureUI();
private:
OwnedArray<Knob> Knobs;
ComponentBoundsConstrainer ResizeBounds;
ResizableCornerComponent *Resizer;
MoonlightAudioProcessor& processor;
};
#include "PluginProcessor.h"
#include "PluginEditor.h"
MoonlightAudioProcessorEditor::MoonlightAudioProcessorEditor (MoonlightAudioProcessor& p)
: AudioProcessorEditor (&p), processor (p)
{
setSize (400, 300);
ConfigureUI();
}
void MoonlightAudioProcessorEditor::ConfigureUI()
{
OrbitKnob = new Knob("Orbit", this);
SpaceKnob = new Knob("Space", this);
InertiaKnob = new Knob("Inertia", this);
Knobs.add(OrbitKnob);
Knobs.add(SpaceKnob);
Knobs.add(InertiaKnob);
for (Knob *knob : Knobs)
{
knob->KnobSlider->addListener(this);
addAndMakeVisible(knob);
knob->setAlwaysOnTop(true);
}
ResizeBounds.setSizeLimits(DEFAULT_WIDTH,
DEFAULT_HEIGHT,
MAX_WIDTH,
MAX_HEIGHT);
Resizer = new ResizableCornerComponent(this, &ResizeBounds);
addAndMakeVisible(Resizer);
setSize(processor._UIWidth, processor._UIHeight);
}
void MoonlightAudioProcessorEditor::paint (Graphics& g)
{
g.setColour (Colours::black);
g.fillAll();
}
void MoonlightAudioProcessorEditor::resized()
{
int width = getWidth();
int height = getHeight();
auto bounds = getLocalBounds();
auto graphicBounds = bounds.removeFromTop(height*.8);
auto orbitBounds = bounds.removeFromLeft(width/3);
auto spaceBounds = bounds.removeFromLeft(width/3);
if (OrbitKnob != nullptr)
{
OrbitKnob->setBounds(orbitBounds);
}
if (SpaceKnob != nullptr)
{
SpaceKnob->setBounds(spaceBounds);
}
if (InertiaKnob != nullptr)
{
InertiaKnob->setBounds(bounds);
}
if (Resizer != nullptr)
{
Resizer->setBounds(width - 16, height - 16, 16, 16);
}
processor._UIWidth = width;
processor._UIHeight = height;
}
Also, I have been using the AudioPluginHost application provided with JUCE to test my plugin. A lot of times the application will crash from a segmentation fault. Then I rebuild the plugin without changing anything and it will work.
I ended up figuring it out.
My components were being initialized after I set the size. A lot of the display logic was in the resize()
function so I needed to set the size after component initialization.