Hello,
I have a few tabComponent and i would like to put a password on one of them. For this, how to be informed if a specific tab has been selected by the user?
Thanks,
Frédéric.
https://docs.juce.com/develop/classTabbedComponent.html#acb0ec8ee87c29825f9326aadb8302b72
Does this do it? It’s labelled virtual so I thinkthe idea is to inherit and override it.
Ho, thank you very much, i didn’t saw it.
Alternatively the TabbedButtonBar is a ChangeBroadcaster, so you could do:
getTabbedButtonBar().addChangeListener (listener);
Is there a function like “onClick()” and a way to use a lambda function that is called when the button is clicked? (like for Button?)
Not built in, but you could create a wrapper:
struct ChangeLambda : private juce::ChangeListener
{
explicit ChangeLambda (juce::ChangeBroadcaster& senderToUse)
: sender (senderToUse)
{
sender.addChangeListener (this);
}
~ChangeLambda() override
{
sender.removeChangeListener (this);
}
void changeListenerCallback (juce::ChangeBroadcaster*) override
{
if (onChange) onChange();
}
std::function<void()> onChange;
private:
ChangeBroadcaster& sender;
};
juce::TabbedComponent tabbedComponent;
ChangeLambda tabConnection { tabbedComponent.getTabbedButtonBar() };
// and setup:
tabConnection.onChange = [this] { doSomething(); };
You can use it with any ChangeBroadcaster
Thank you, it seems very interesting, but since i don’t understand very well the c++ code here, i tried and the compilator says:
error: class ‘ChangeLambda’ does not have any field named ‘sender’
| : sender (senderToUse)
Something is missing?
Sorry, that was my bad. I decided on a different name for the member variable, but didn’t change it everywhere. I edited the code above.
Basically we store the ChangeBroadcaster reference, that way we can deregister ourselves as listener when we are destroyed.
There is no more error in compilation, but i tried with:
void doSomething()
{
cout<<"Hello"<<endl;
}
and i see no message when i clic. Is there something else missing?
I copied the code in a playground and it works for me.
Maybe test, if the cout works at all?
I used DBG to test:
MainComponent::MainComponent()
{
addAndMakeVisible(tabs);
tabConnection.onChange = [this]
{
DBG ("Changed");
};
tabs.addTab("First", juce::Colours::darkblue, new juce::Slider(), true);
tabs.addTab("Second", juce::Colours::darkblue, new juce::Slider(), true);
tabs.addTab("Third", juce::Colours::darkblue, new juce::Slider(), true);
tabs.addTab("Fourth", juce::Colours::darkblue, new juce::Slider(), true);
setSize (600, 400);
}
void MainComponent::resized()
{
tabs.setBounds(getLocalBounds());
}
// and those members:
// Your private member variables go here...
juce::TabbedComponent tabs { juce::TabbedButtonBar::TabsAtTop };
ChangeLambda tabConnection { tabs.getTabbedButtonBar() };
Sorry for my previous message. It works very well. In my case i use a pointer juce::TabbedComponent *tab; instead of an object, so i declared tabConnection as a pointer too.
Thank you very much!
(This is very useful, but i have to understand exactly what this code means.)
Thanks for the correction, Daniel. Say, would this be a good place to use the Component Safe Pointer/Weak Reference classes? You deregister your ChangeLambda in the destructor, but isn’t it possible that the ‘this’ in the lamdba gets deleted?
The this pointer is always a problem. Here it is safe, because the struct owning the lambda is owned by the same this.
If the lambda was executed asynchronously then a SafePointer or WeakReference would indeed be required.
Btw, wasn’t meant as correction. The virtual method is also a good solution.