Label values do not update visually


#1

Hi,

I am writing regarding an subcomponent drawing update problem I have. I am creating a minimalist GUI application. The aim is to print continues values on a Label component. I have now taken following steps.

1. I have created a GUI sub component class called CustomComponent in the Introjucer. The Class introduces a Label called intLabel
2. I have created a reference to the sub class in MainComponent and made the sub component visible
3. in the CustomComponent I have created a method called updateLabel() which embodies intLabel-setText() method as follows

intLabel->setText(String (receiveOSCVal), sendNotification);

The setText() within updateLabel() method works as expected when called through CustomComponent constructor. That is, intLabel’s field reveives values and they get printed as expected.

Now the problem is following. If the updateLabel() method is called through another class the text field does not update. However, sent values are stored in the intLabel. I have checked this with getText() method as follows

intLabel->getText());

I am asking what should I do differently in order to make the intLabel update visually? Your help is much appreciated.

Cheers

Matti


#2

Usually if something isn't appearing on the screen the repaint() method is a good thing to try: label->repaint()?


#3

I concidered that also bazrush - I added repaint() calls before and after the setText() call. However, the resulting is still the same - no update in the text field.

Let me eloborate my application logic a bit. Now I am drawing a button on the MainComponent and a Label on the CustomComponent.

Further, my application logic requires a click of the button before values are sent via updateLabel() which writes values via intLabel->setText().

Could the specific update problem exist because the button on the MainComponent is clicked first and does this influence CustomComponet behaviour somehow?

 

 


#4
So you've got 

class MyComponent 
: 
public Component
{
public:
MyComponent() { addAndMakeVisible(someLabel); someLabel.setBounds(..somewhere on screen...); }
void update(const String & textToUpdate) { someLabel.setText(textToUpdate); }
private:
Label someLabel; 
};

Anyway, looks like setText() calls repaint() anyway, so this should work.

Want to post the actual code


#5

Yes that is basically what I intended. I will gladly send my code. Here are both header and cpp files of the CustomComponent.

Please let me know if you need some additional info.

CustomComponent.cpp

#include "CustomComponent.h"

//==============================================================================
CustomComponent::CustomComponent ()
{
    addAndMakeVisible (intLabel = new Label ("intLabel", String::empty));
    intLabel->setFont (Font (15.00f, Font::plain));
    intLabel->setJustificationType (Justification::centredLeft);
    intLabel->setEditable (false, false, false);
    intLabel->setColour (TextEditor::textColourId, Colours::black);
    intLabel->setColour (TextEditor::backgroundColourId, Colour(0x00000000));

    // this call works as expected - values get printed on the intLabel
    setIntTextField(900);

    setSize (600, 400);

}

CustomComponent::~CustomComponent()
{
    intLabel = nullptr;
}

void CustomComponent::paint (Graphics& g)
{
     g.fillAll (Colours::white);
}

void CustomComponent::resized()
{
    intLabel->setBounds (proportionOfWidth (0.5000f) - ((150) / 2), proportionOfHeight (0.3000f) - ((24) / 2), 150, 24);
}

void CustomComponent::setIntTextField(const int& OSCUpdate)
{
    intLabel->setText(String (OSCUpdate), sendNotification);
    DBG("Int Text Through DBG " << intLabel->getText()); // this returns any number sent earlier
    intLabel->repaint(); 
}

CustomComponent.h

class CustomComponent  : public Component
{
public:
    CustomComponent ();
    ~CustomComponent();

    void setIntTextField(const int& OSCUpdate);
    void paint (Graphics& g);
    void resized();

private:
    ScopedPointer<Label> intLabel;
};

and in my OSC class I create an instance of a CustomComponent called customOSCCall which is used as follows

customOSCCall.setIntTextField(intMessage);

 


#6

Hi.

Why did you write

void CustomComponent::setIntTextField(const int& OSCUpdate)

instead of

void CustomComponent::setIntTextField(const int OSCUpdate)

?
 


 


#7

There's nothing wrong with that bit of code.  I even tested it to make sure I'm not being dizzy.  I get a nice updating number on the screen.

Is that debug message getting printed?  Do you have TWO CustomComponents by accident or something? 


#8

That would be classical mistake having two objects and cross referencing them. However, that should not be source of an error this time.

The DBG-message gets printed properly. One think comes to my mind. Could it be that the screen does not update beacause I trigger the updateLabel() through an external application? That is I send OSC messages via PureData patch. I could debug this by adding a button on a Juce application and calling updateLabel() method through that. What do you think?

Edit on Friday 12. 2014, 4:45 PM

Adding a slider to the CustomComponent class works as expected. That is, when sending slider values to updateLabel() method the intLabel updates it's values.

setIntTextField(slider->getValue());

Summarizing this. I need to find answer to the question how Juce Label Component listens incoming messages. In particular, in my case how to make the intLabel to update it's GUI when called via external input device.

(re)Search goes on!


#9

Well if setIntTextField is being called with an integer you'll get the same result no matter what you call it with. How long is the rest of the code? Can you make a simple example that shows the failure?


#10

Hi bazrush - thank you for keeping up with me.

I'll make a copy of the project and upload it into Git.

Meanwhile could the problem lurk behind using different threads the example app might use for handling OSC (caller class) and GUI (callee class)?


#11

 

Hi,

I added source files to GitHub for viewing.

They can be found via link below

https://github.com/Mantsuria/Juce-and-OSC

The aim of the program is to print values on a label component. This works as expected when values are sent via slider component. However, the problem is that the label values do not get printed visually when they are tgriggered via an external application sending osc messages.

On a practical level ReceiveOSC class receives osc messages and sends them forward by calling the CustomComponent class method called setFloatTextField(). The label within method stores the values but they are not displayed.

Would be great if someone coud point me towards right direction.

Cheers,

Matti

 


#12

I'll have a quick peek tomorrow - but might be Wednesday before I can have a proper look! But if no-one else gets back to you I'll definitely get to it :)


#13

There's a separate problem you might have with having two threads - but that's minor at this stage and it'll work most of the time.   The main problem is you have two CustomComponents.   One in MainContentComponent and the other inside ReceiveOSC. 

There are a million solutions to this.  You could pass a reference or pointer to the CustomComponent in to your ReceieveOSC function.  You could make a custom listener callback, you could do something C++11 with a lambda. Or you could look at the various JUCE classes for passing messages around.  Try AsyncUpdater and ChangeBroadcaster as starting points. 

And for the inter-thread solution ScopedLock, or AbstractFIFO if you want more of a headache but don't want to use locks ..

Hope that helps!

 


#14

PS.  It's _very_ useful to double check the address of an object is consistent  in the debugger when you have a frustrating problem like this one.  

 

PPS.  I think a good solution here is to add a ListenerList, and an addListener() method to your ReceiveOSC object.

It might want to send messages to multiple destinations, and you can use a custom set of parameters in the callback to represetent the OSC data.  

 

Look in juce_AnimatedPosition.h for a simple example of how this might work.  


#15

Thank you bazrush for your input - wow that was a lot to digest :)

Anyway - I will go through your advice gradually and report my learning outcomes to this thread.

All the best!

Mti