Radio buttons not working as expected (even in the Juce example)


#1

Hi All,

I’ve been trying to have 3 TextButtons which I are part of a RadioGroup and therefore only one can be ‘On’ at a given time:

class OrderSelect : public Component
{
    TextButton firstOrder {"1st Order"};
    TextButton secondOrder {"2nd Order"};
    TextButton thirdOrder {"3rd Order"};
    public:
    OrderSelect()
    {
        firstOrder.setClickingTogglesState(true);
        firstOrder.setRadioGroupId (1001);
        addAndMakeVisible(firstOrder);
        secondOrder.setClickingTogglesState(true);
        secondOrder.setRadioGroupId (1001);
        addAndMakeVisible(secondOrder);
        thirdOrder.setClickingTogglesState(true);
        thirdOrder.setRadioGroupId (1001);
        addAndMakeVisible(thirdOrder);
        firstOrder.setToggleState(true, NotificationType::dontSendNotification);
        secondOrder.setToggleState(false, NotificationType::dontSendNotification);
        thirdOrder.setToggleState(false, NotificationType::dontSendNotification);
    };
    private:
    void resized() override
    {
        int noOfOrders = 3;
        auto buttonHeight =  getHeight() / noOfOrders;
        firstOrder.setBounds (0, 0, getWidth(), buttonHeight );
        secondOrder.setBounds(0, buttonHeight, getWidth(), buttonHeight );
        thirdOrder.setBounds (0, buttonHeight*2, getWidth(), buttonHeight );
    }
};

This however results in 3 buttons which can all be clicked to ‘On’ and never turned off. I’ve checked the Juce example (https://docs.juce.com/master/tutorial_radio_buttons_checkboxes.html) and when I build that it seems to suffer the same issue?

Any help?


#2

The only think I can see is you do not set a buttonWidth, but you call it in resized(). Components nog having proper heights and widths is a common mistake that leads to unpredictable behavoir - I’ve wasted many hours because of such errors… Try a setSize in the constructor.


#3

Oh and why is resized() private?


#4

Hi tomto66, thanks for the reply! setSize() has made no difference. In the example Juce provide the two issues you’ve mentioned are corrected but the overall problem is still there. The issue goes away if I comment out .setRadioGroupId(), however this defeats the point…
Would love someone to try the linked example and see if they suffer the same issue?


#5

I copied your code into an empty Application and it worked as expected.
However I noticed, that the colour of the on state is very subtly different from the off state.

You can make it more obvious by adding these two lines to your constructor (the values will be inherited to the child components):

    getLookAndFeel().setColour (TextButton::buttonColourId, Colours::red);
    getLookAndFeel().setColour (TextButton::buttonOnColourId, Colours::green);

#6

Hi Daniel,

Thanks for the response. I’ve modified the Juce example code and added your suggestion but I’m still getting the same issue.

class MainContentComponent   : public Component
{
public:
    //==============================================================================
    enum RadioButtonIds
    {
        GenderButtons = 1001
    };

    MainContentComponent()
    {
        addAndMakeVisible (genderLabel);


        maleButton  .onStateChange = [this] { updateToggleState (&maleButton,   "Male");   };
        femaleButton.onStateChange = [this] { updateToggleState (&femaleButton, "Female"); };
        maleButton  .setToggleState (true, dontSendNotification);
        femaleButton.setToggleState (false, dontSendNotification);
        maleButton  .setClickingTogglesState(true);
        femaleButton.setClickingTogglesState(true);
        maleButton  .setRadioGroupId (GenderButtons);
        femaleButton.setRadioGroupId (GenderButtons);
        getLookAndFeel().setColour (TextButton::buttonColourId, Colours::red);
        getLookAndFeel().setColour (TextButton::buttonOnColourId, Colours::green);
        addAndMakeVisible (maleButton);
        addAndMakeVisible (femaleButton);
        
        setSize (400, 300);
    }

    ~MainContentComponent() {}
    
    void paint (Graphics& g) override {
        g.fillAll (Colours::darkgrey);
    }
    
    void resized() override
    {
        genderLabel .setBounds (10, 10, 120, 20);
        maleButton  .setBounds (20, 40, 130, 20);
        femaleButton.setBounds (20, 70, 130, 20);
    }

    void updateToggleState (Button* button, String name)
    {
        auto state = button->getToggleState();
        String stateString    = state ? "ON" : "OFF";
        String selectedString = state ? " (selected)" : "";

        Logger::outputDebugString (name + " Button changed to " + stateString);
        button->setButtonText (name + selectedString);
    }

private:
    Label genderLabel         { {}, "I identify my gender as..."};
    TextButton maleButton     { "Male" },
               femaleButton   { "Female" };
    
    //==============================================================================
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
};

Each button can be selected and then shows the ‘(selected)’ in text next to it… Only both can go into that state at the same time and then never changed back to unselected


#7

Unfortunately your code works here without problems… I’m afraid I have no idea, what’s going wrong:


#8

Work fine for me too… (I’m on OS X and U ?), suggest delete and reload the juce library ?


#9

It’s working as expected for me too. What version of JUCE are you using?


#10

Using Juce 5.4.1


#11

I’m not sure what else could be the issue then, it seems to be working fine. Can you check the widgets demo in the DemoRunner app? There is a set of radio buttons on the “Buttons” tab here which should be behaving the same:


#12

Okay great, I’ve ran the widgets demo and it works as expected for me. I’m away until Saturday but I will copy over the relevant lines from that demo into my project and check whether the issue persists. Thanks


#13

And if you build the widgets demo, is it ok too ?