Loading...
Searching...
No Matches
Tutorial: The Label class

This tutorial introduces the Label class, which is a component for displaying text. A Label component can also be set to be editable so it's really useful for displaying text and simple text entry.

Level: Beginner

Platforms: Windows , macOS , Linux , iOS , Android

Classes: Label, TextEditor, Font, Colours

Getting started

Download the demo project for this tutorial here: PIP | ZIP . Unzip the project and open the first header file in the Projucer.

If you need help with this step, see Tutorial: Projucer Part 1: Getting started with the Projucer.

The demo project

The demo project includes a number of labels. Some of these are for displaying text, but one of them is for entering text. Run the demo project and it should look like the following screenshot:

The initial appearance of the application

When you click on the label with the white background it becomes editable, the label shows a subtle border, and a caret appears. This is shown in the following screenshot.

The application with the text entry label focused

Text can then be entered into this label as shown below:

Entering text into the text entry label

When you hit return or click away from the label it goes out of its editable state. This commits a change that is broadcasted to its listeners. In this case we convert the text to uppercase and display it in another label:

The text is converted to uppercase and displayed in another label

This illustrates several different uses of the Label class for both displaying and entering text. There are actually five labels here that are used in slightly different ways:

  • The green label at the top that is used as a heading.
  • The two orange labels that are used to display other fixed text.
  • The two rectangular boxes that are used to display dynamically changing text (one of which is to allow text entry from the user).

The second of the rectangular boxes is very slightly greyed out to distinguish it from the text entry box.

Displaying text

This tutorial covers most of the main features of the Label class. The most fundamental feature of a label is that it displays some text! While you can draw your own text in your component's paint() function (see Tutorial: The Graphics class) it is usually much more convenient to manage the layout of text using Label objects (or TextEditor objects in some cases).

As you would expect, the text within a Label object can be displayed in any font, font size, bold, italics, and so on. The text can also be justified (aligned) within the component bounds to the left, right, centre, top, bottom, and using various other options.

Note
The Label class can only contain a single run of text in the same font, size, and justification. To display multiple runs of text in different styles (as you would find in a word processor application) see the TextEditor class. The TextEditor class can also include horizontal and vertical scroll bars to display large amounts of text.

If the bounds of the component are too small to display all of the text requested then the Label class will try a few things to make the text fit. First, it will make the glyphs of the font a little narrower. If the glyphs are too narrow then the text will be unreadable, so beyond a certain point it gives up. In this case it truncates the text showing an ellipsis (...) at the end to show that this has been done. You can try this now by typing in the text "The quick brown fox jumps over the lazy dog" in the text entry label. In fact you can copy the text ("CMD-C" to copy on Mac OS X or "Ctrl-C" on Windows) from this page and paste it into the label using keyboard shortcuts ("CMD-V" to paste on Mac OS X or "Ctrl-V" on Windows). This capability is built in without you needing to add any code!

The result should be something like this:

Two ways that the Label class copes with too much text

The original text just about fits but it is slightly squashed in the horizontal axis. The uppercase version is going to be a little wider since uppercase glyphs are usually wider than lowercase glyphs. The Label class decided that the uppercase version is too wide for it to squash the text in the horizontal axis and keep it readable. In this case it has truncated the text at the "L" in "LAZY" and added the ellipsis.

Note
You can change the amount by which the text will be scaled using the Label::setMinimumHorizontalScale() function for each Label object. Using a value of 1.0f will disable the scaling. You can measure the height required for a single line in a particular font using the Font::getHeight() function. To measure the width that an entire string would require to fit on a single line you can use the Font::getStringWidth() function.

Basic label configuration

In the MainContentComponent constructor each of the labels in our application is configured. First we set up the title with a 16-point bold font, the text it should contain, the colour of the text, and we justify the text to the centre.

Add the label to the parent component:

addAndMakeVisible (titleLabel);

Set the font for the label:

titleLabel.setFont (juce::Font (16.0f, juce::Font::bold));

Set the text to be displayed within the label:

titleLabel.setText ("Click in the white box to enter some text...", juce::dontSendNotification);

Set the colour of the label text:

titleLabel.setColour (juce::Label::textColourId, juce::Colours::lightgreen);

Justify the display of the label text:

titleLabel.setJustificationType (juce::Justification::centred);
Note
The Justification::centred value centres the text in both vertical and horizontal axes. Have a look at the Justification class for more options.

Attaching a label to another component

As its name suggests, a Label component is often used as a label for another component. In this case a Label object can be attached to another component. Once a label is attached only the owner component needs to be positioned. The attached label will follow its owner around the parent component. In our case we want the inputLabel object (that displays the text Text input: ) to be attached to the inputText object. The second argument to the Label::attachToComponent() function states whether the label should be attached to the left or above the owner. The true argument means that it should be attached to the left:

addAndMakeVisible (inputLabel);
inputLabel.setText ("Text input:", juce::dontSendNotification);
inputLabel.attachToComponent (&inputText, true);
inputLabel.setColour (juce::Label::textColourId, juce::Colours::orange);
inputLabel.setJustificationType (juce::Justification::right);

The labels to display the uppercase text are set up similarly:

addAndMakeVisible (uppercaseLabel);
uppercaseLabel.setText ("Uppercase:", juce::dontSendNotification);
uppercaseLabel.attachToComponent (&uppercaseText, true);
uppercaseLabel.setColour (juce::Label::textColourId, juce::Colours::orange);
uppercaseLabel.setJustificationType (juce::Justification::right);
addAndMakeVisible (uppercaseText);
uppercaseText.setColour (juce::Label::backgroundColourId, juce::Colours::darkblue);

In the resized() function we need to position only three of our five labels:

void resized() override
{
titleLabel .setBounds (10, 10, getWidth() - 20, 30);
inputText .setBounds (100, 50, getWidth() - 110, 20);
uppercaseText.setBounds (100, 80, getWidth() - 110, 20);
}

Making a label editable

The final label that we set up in the MainContentComponent constructor is the editable text field.

addAndMakeVisible (inputText);
inputText.setEditable (true);
inputText.setColour (juce::Label::backgroundColourId, juce::Colours::darkblue);
inputText.onTextChange = [this] { uppercaseText.setText (inputText.getText().toUpperCase(), juce::dontSendNotification); };
Note
The default behaviour when setting the label to editable using the Label::setEditable() function is to show the editor on a single click. The label can be set up to be editable on a double-click instead. If the user clicks off the label after entering some text then this will be confirmed even if the user doesn't hit the "Return" key. You can also changes this to make sure that users must hit the "Return" key to confirm data entry, if you prefer. See the API reference for this function for more information.
Exercise
Add a button to the interface and use this to clear the text entry label. (See Tutorial: Listeners and Broadcasters.)

Responding to changes

The lambda function is the callback for the Label::onTextChange helper object. Here we get the entered text, convert it to uppercase using the String class, and set the text of the uppercaseText label.

inputText.onTextChange = [this] { uppercaseText.setText (inputText.getText().toUpperCase(), dontSendNotification); };
@ dontSendNotification
No notification message should be sent.
Definition juce_NotificationType.h:48
Note
We can use sendNotification instead of dontSendNotification when calling Label::setText(). This will cause a label's listeners to be notified of the change (if the text is different from its current contents) in addition to the user changing the text from the user interface.
Exercise
Add another label that displays the text entered in lowercase.

Other customisations

There are a few other customisations that can be made. In particular labels can display multiline text. You may also want to customise the editor for editable labels.

Displaying multiline text

While the TextEditor class is more flexible for large amounts of text, the Label class can display multiple lines of text. To do this, you just need to ensure that the height of the component is large enough to display more than one line of text.

To illustrate this, add the following member to the MainContentComponent class:

juce::Label infoLabel;

And add the following code to the MainContentComponent constructor:

addAndMakeVisible (infoLabel);
juce::String infoText;
infoText << "This simple application takes some text input from the user, ";
infoText << "converts it to uppercase, and displays this in another label. ";
infoText << "The application demonstrates a number of useful features of the Label class.";
infoLabel.setText (infoText, juce::dontSendNotification);
infoLabel.setColour (juce::Label::backgroundColourId, juce::Colours::darkblue);

Finally, set the bounds of the infoLabel component in the resized() function:

infoLabel.setBounds (10, 110, getWidth() - 20, getHeight() - 120);
Note
You might need to adjust the bounds a little if you added a button and another label in the earlier exercises.

Run the application and it should look something like this:

Displaying multiline text

Changing the editor appearance

Some of the editor features can be set via the Label class itself. When the editor is created the Label class copies the font style and colours to the editor. Some of the Label::ColourIds values relate to the editor. For example, to change the border around the label when it is being edited you can use the Label::outlineWhenEditingColourId value for the Component::setColour() function:

addAndMakeVisible (inputText);
inputText.setEditable (true);
inputText.setColour (juce::Label::backgroundColourId, juce::Colours::darkblue);
inputText.setColour (juce::Label::outlineWhenEditingColourId, juce::Colours::orangered);

Other customisations can be achieved by implementing the Label::onEditorShow helper object. For example, you could make the text italic when being edited like this:

inputText.onEditorShow = [this]
{
auto* editor = inputText.getCurrentTextEditor();
auto editorFont = editor->getFont();
editorFont.setItalic (true);
editor->setFont (editorFont);
};
Note
In practice — especially for large-scale applications — you would probably use the LookAndFeel class to customise the appearance of all of your components for consistency across your application.

Summary

This tutorial has examined the Label class. While it is very easy to use, there are a number of useful features that make it powerful. We have covered:

  • Changing the font of the text displayed in the label.
  • Changing the colours of the text displayed in the label.
  • Using a label as a simple text editor and customising its appearance.
  • Displaying multiline text.

See also

linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram