自定义子组件已添加但不可见

Custom Child Components Added But Not Visible

我正在使用 JUCE 框架创建一个音频插件。我创建了一个继承自 Component class 的 Knob class。我的 Knob class 包含对 SliderLabel 的引用。

在我的 AudioProcessorEditor class 中,我初始化了几个 Knob 对象。但是,Component 中的 none 在 运行 时可见。我做错了什么或漏掉了一步吗?

我尝试直接在 AudioProcessorEditor class 中声明 SliderLabel 对象。当我这样做时,我能够在 运行 时成功地看到 SliderLabel 对象。所以我觉得这个问题涉及到我的 Knob class.

Knob.h

#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)
};

Knob.cpp

#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);
}

PluginEditor.h

#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;
};

PluginEditor.cpp

#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;
}

此外,我一直在使用 JUCE 提供的 AudioPluginHost 应用程序来测试我的插件。很多时候,应用程序会因分段错误而崩溃。然后我在不做任何更改的情况下重建插件,它就可以工作了。

您在 Knob::Paint(Graphics& g)

中遗漏了对 Component::Paint(g) 的调用

我终于搞清楚了。

设置大小后我的组件正在初始化。很多显示逻辑都在resize()函数中,所以我需要在组件初始化后设置大小。