Why the slider is not shown?

Hi everyone:
Why the slider is not shown?
Below is the code:
class MainContentComponent;

class MessageSendComponent :public Component
{
public:
	MessageSendComponent()
	{
		addAndMakeVisible(slider);
	}

	~MessageSendComponent()
	{

	}
	//friend void MainContentComponent::sliderValueChanged(Slider* slider);
	friend MainContentComponent;

	void paint(Graphics& g) override 
	{
		//g.fillAll(Colours::lightblue);
	}
	//void resized() override 
	//{


	//}
private:

	Slider slider;
	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MessageSendComponent)

};







//==============================================================================
class MainContentComponent  : public Component,
                              private MidiKeyboardStateListener,
	                          public Slider::Listener
{
public:
    MainContentComponent()
      : keyboardComponent (keyboardState, MidiKeyboardComponent::horizontalKeyboard),
        startTime (Time::getMillisecondCounterHiRes() * 0.001)
    {
        setOpaque (true);

		addAndMakeVisible(messagesendcomponent);

        addAndMakeVisible (midiOutputListLabel);
        midiOutputListLabel.setText ("MIDI Output:", dontSendNotification);
        midiOutputListLabel.attachToComponent (&midiOutputList, true);

        addAndMakeVisible (midiOutputList);
        midiOutputList.setTextWhenNoChoicesAvailable ("No MIDI Outputs Enabled");
        auto midiOutputs = MidiOutput::getDevices();
        midiOutputList.addItemList (midiOutputs, 1);
        midiOutputList.onChange = [this] { setMidiOutput (midiOutputList.getSelectedItemIndex()); };

		setMidiOutput(midiOutputList.getSelectedItemIndex());
        // if no enabled devices were found just use the first one in the list
        if (midiOutputList.getSelectedId() == 0)
            setMidiOutput (0);

        addAndMakeVisible (keyboardComponent);
        keyboardState.addListener (this);

        addAndMakeVisible (midiMessagesBox);
        midiMessagesBox.setMultiLine (true);
        midiMessagesBox.setReturnKeyStartsNewLine (true);
        midiMessagesBox.setReadOnly (true);
        midiMessagesBox.setScrollbarsShown (true);
        midiMessagesBox.setCaretVisible (false);
        midiMessagesBox.setPopupMenuEnabled (true);
        midiMessagesBox.setColour (TextEditor::backgroundColourId, Colour (0x32ffffff));
        midiMessagesBox.setColour (TextEditor::outlineColourId, Colour (0x1c000000));
        midiMessagesBox.setColour (TextEditor::shadowColourId, Colour (0x16000000));

        setSize (600, 400);
    }

    ~MainContentComponent()
    {
        keyboardState.removeListener (this);
    }

	void sliderValueChanged(Slider* slider) override
	{
		if (slider == &(messagesendcomponent.slider))
		{
			//pitchWheel (int channel, int position)
			int channel = 4;
			int position = 54;
			auto m = MidiMessage::pitchWheel(channel, position);
			m.setTimeStamp(Time::getMillisecondCounterHiRes() * 0.001);
			addMessageToList(m, "Slider send Message");
			CurrentOutDevice->sendMessageNow(m);
		}

	}

    void paint (Graphics& g) override
    {
        g.fillAll (Colours::black);
    }

    void resized() override
    {
        auto area = getLocalBounds();

        midiOutputList    .setBounds (area.removeFromTop (36).removeFromRight (getWidth() - 150).reduced (8));
        keyboardComponent.setBounds (area.removeFromTop (80).reduced(8));
		messagesendcomponent.setBounds(area.removeFromLeft(100));
        midiMessagesBox  .setBounds (area.reduced (8));
    }

private:
    static String getMidiMessageDescription (const MidiMessage& m)
    {
        if (m.isNoteOn())           return "Note on "          + MidiMessage::getMidiNoteName (m.getNoteNumber(), true, true, 3) + ":" + String::toHexString(m.getRawData(), m.getRawDataSize());
        if (m.isNoteOff())          return "Note off "         + MidiMessage::getMidiNoteName (m.getNoteNumber(), true, true, 3) + ":" + String::toHexString(m.getRawData(), m.getRawDataSize());
        if (m.isProgramChange())    return "Program change "   + String (m.getProgramChangeNumber()) + ":" + String::toHexString(m.getRawData(), m.getRawDataSize());
        if (m.isPitchWheel())       return "Pitch wheel "      + String (m.getPitchWheelValue()) + ":" + String::toHexString(m.getRawData(), m.getRawDataSize());
        if (m.isAftertouch())       return "After touch "      + MidiMessage::getMidiNoteName (m.getNoteNumber(), true, true, 3) +  ": " + String (m.getAfterTouchValue()) + ":" + String::toHexString(m.getRawData(), m.getRawDataSize());
        if (m.isChannelPressure())  return "Channel pressure " + String (m.getChannelPressureValue()) + ":" + String::toHexString(m.getRawData(), m.getRawDataSize());
        if (m.isAllNotesOff())      return "All notes off:" + String::toHexString(m.getRawData(), m.getRawDataSize());
        if (m.isAllSoundOff())      return "All sound off:" + String::toHexString(m.getRawData(), m.getRawDataSize());
        if (m.isMetaEvent())        return "Meta event:" + String::toHexString(m.getRawData(), m.getRawDataSize());

        if (m.isController())
        {
            String name (MidiMessage::getControllerName (m.getControllerNumber()));

            if (name.isEmpty())
                name = "[" + String (m.getControllerNumber()) + "]";

            return "Controller " + name + ": " + String (m.getControllerValue())+":"+ String::toHexString(m.getRawData(), m.getRawDataSize());
        }

        return "Unkown message:" + String::toHexString (m.getRawData(), m.getRawDataSize());
    }

    void logMessage (const String& m)
    {
        midiMessagesBox.moveCaretToEnd();
        midiMessagesBox.insertTextAtCaret (m + newLine);
    }

    /** Starts listening to a MIDI input device, enabling it if necessary. */
    void setMidiOutput (int index)
    {
		CurrentOutDevice.reset(MidiOutput::openDevice(index));
		midiOutputList.setSelectedId(index + 1, dontSendNotification);
    }

    void handleNoteOn (MidiKeyboardState*, int midiChannel, int midiNoteNumber, float velocity) override
    {
        auto m = MidiMessage::noteOn (midiChannel, midiNoteNumber, velocity);
        m.setTimeStamp (Time::getMillisecondCounterHiRes() * 0.001);
		addMessageToList(m, "Keyboard send Note On");
		CurrentOutDevice->sendMessageNow(m);
    }

    void handleNoteOff (MidiKeyboardState*, int midiChannel, int midiNoteNumber, float /*velocity*/) override
    {
        auto m = MidiMessage::noteOff (midiChannel, midiNoteNumber);
        m.setTimeStamp (Time::getMillisecondCounterHiRes() * 0.001);
		addMessageToList(m, "Keyboard send Note Off");
		CurrentOutDevice->sendMessageNow(m);
    }
 
    void addMessageToList (const MidiMessage& message, const String& source)
    {
        auto time = message.getTimeStamp() - startTime;

        auto hours   = ((int) (time / 3600.0)) % 24;
        auto minutes = ((int) (time / 60.0)) % 60;
        auto seconds = ((int) time) % 60;
        auto millis  = ((int) (time * 1000.0)) % 1000;

        auto timecode = String::formatted ("%02d:%02d:%02d.%03d",
                                           hours,
                                           minutes,
                                           seconds,
                                           millis);

        auto description = getMidiMessageDescription (message);

        String midiMessageString (timecode + "  -  " + description + " (" + source + ")"); // [7]
        logMessage (midiMessageString);
    }

    //==============================================================================
    AudioDeviceManager deviceManager;           
    ComboBox midiOutputList;                     
    Label midiOutputListLabel;

    MidiKeyboardState keyboardState;            
    MidiKeyboardComponent keyboardComponent;    

    TextEditor midiMessagesBox;
    double startTime;
	//
	MessageSendComponent  messagesendcomponent;
	//
	std::unique_ptr<MidiOutput> CurrentOutDevice=nullptr;
    //==============================================================================
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
};

2

Best regards!

Hi

You have to give the slider some bounds within MessageSendComponent::resized()

void resized() override
{
    slider.setBounds (getLocalBounds());
}
1 Like

Well I think you should have a read on the very basics how juce Components work, try going through this tutorial:

https://docs.juce.com/master/tutorial_component_parents_children.html

What is obvious in your example: You make the slider visible but don’t set it’s position and size within the Component. So how do you expect the slider to appear if you don’t give any information on where and how big it should appear? The place to do this is the resized method of your component that you commented out

1 Like

Why the slider in the child class seems not respond to slider value change?

void sliderValueChanged(Slider* slider) override
	{
		if (slider == &(messagesendcomponent.slider))
		{
			//pitchWheel (int channel, int position)
			/*int channel = 4;
			int position = 54;
			auto m = MidiMessage::pitchWheel(channel, position);
			m.setTimeStamp(Time::getMillisecondCounterHiRes() * 0.001);*/
			int midiChannel = 10;
			int midiNoteNumber = 10;
			auto m = MidiMessage::noteOff(midiChannel, midiNoteNumber);
			m.setTimeStamp(Time::getMillisecondCounterHiRes() * 0.001);
			addMessageToList(m, "Slider send Message");
			CurrentOutDevice->sendMessageNow(m);
		}

	}

Hi @caoleiwe,

I would double check if listener is set for messagesendcomponent. Something like this:
messagesendcomponent..addListener (this);
in a constructor of class declared as Slider::Listener, with sliderValueChanged method.
This is better described in tutorial The Slider class.

If it is not that problem, next step would be to set a breakpoint in sliderValueChanged and debug the app in IDE.

Regards.
Mateusz

1 Like

It is definitely that problem, nowhere in the example code is the slider being registered to be listened to.

1 Like

Thank you very much!
It is exactly that problem.