/!\ Note that this page was written for GTK3. The contents largely still applies to GTK4, although some details may have changed. /!\

Labels

GtkLabel is a workhorse widget that occurs multiple times in any average application window. This page is mainly concerned with two aspects of labels: Controlling how long, wrapping labels interact with window size, and ellipsization.

Wrapping labels

Two properties control the wrapping of the labels text:

  GtkLabel::wrap-mode: Controls whether to wrap only at word boundaries, or anywhere

and

  GtkLabel::wrap: If set, wrap lines if the text becomes too wide

One normally only sets the wrap property to TRUE. It is safe to leave the wrap-mode property at its default value, PANGO_WRAP_WORD.

When wrapping is enabled, the same label can appear with multiple different height/width combinations, as can be seen in this example:

unwrapped-label.png

halfwrapped-label.png

wrapped-label.png

How far the label actually wraps depends on the context in which it is used, and on the geometry management of its parent container. There are two properties that allow you to influence the amount of wrapping:

  GtkLabel::width-chars: Specifies the minimum width of a wrapping label

and

  GtkLabel::max-width-chars: Specified the natural width of a wrapping label 

Note that both of these properties are using characters as unit. They are converted to pixels using the average character width of the current font.

Labels in non-resizable windows

When putting a wrapping label into a non-resizable window, this is the typical result:

noresizable-wrapping-label.png

This happens even if the label is marked as wrapped. The window sizes itself to give the label its natural width. Therefore, to fix this situation, you need to set max-width-chars to give the label a smaller natural width.

  win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (win), "Window");
  gtk_window_set_resizable (GTK_WINDOW (win), FALSE);
  label = gtk_label_new ("<big>This is a long text that might need to be wrapped</big>");
  gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
  g_object_set (label, "margin", 20, NULL);
  gtk_container_add (GTK_CONTAINER (win), label);

  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
  gtk_label_set_max_width_chars (GTK_LABEL (label), 30);

And the result is this:

noresizable-label-fixed.png

Labels in resizable windows

When putting a wrapping label in a resizable window, the typical result is this:

resizable-wrapping-label.png

What is happening here is that the window sizes itself to accommodate the height of the label when fully wrapped, even though the label fits unwrapped. To improve this situation, we can set width-chars on the label to prevent the fully wrapped state from being considered when the window determines its height. In addition, we can set the default width of the window to something smaller than the width of the fully unwrapped label. Note that the default width is specified in pixels.

  win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (win), "Window");
  gtk_window_set_resizable (GTK_WINDOW (win), TRUE);
  label = gtk_label_new ("<big>This is a long text that might need to be wrapped</big>");
  gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
  g_object_set (label, "margin", 20, NULL);
  gtk_container_add (GTK_CONTAINER (win), label);

  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);

  gtk_window_set_default_size (GTK_WINDOW (win), 200, -1);
  gtk_label_set_width_chars (GTK_LABEL (label), 30);

With these changes, the window comes up like this:

resizable-label-fixed.png

Aligning labels with other widgets

Sometimes a label needs to wrap, but should fill the width that is provided by another widget. Out of the box, there is no good way to do this, since GTK+ doesn't have a way to say "don't grow larger than this other widget". Most of the time, it is possible to arrange this with a combination of the following:

  • Put the label in the same container as the other widget, so they both get allocated the same width
  • Set the labels max-width-chars to a reasonable minimum line width (note that choosing a too small value here will force your window to be tall)
  • Set the label to wrap, wrap-mode = words
  • Set the label to have halign = fill, xalign = 0.0

label-align-rewrap.png

Fixed number of lines

Sometimes it is necessary to keep text to a certain number of lines. One approach is to turn off automatic wrapping and rely on inserting line breaks in the text manually.

  label = gtk_label_new ("<big>This is a long text\nthat might need\nto be wrapped</big>");

This can be problematic because you have to balance line length yourself, and translators may inadvertently change the number of lines by removing or adding line breaks in their translations.

manually-wrapped.png

Also, text with fixed breaks is ellipsized in each line, which may look unexpected:

manually-wrapped-ellipsized.png

A better alternative is to go back to automatic wrapping, and tell GTK+ how many lines of text you want, using gtk_label_set_lines():

  label = gtk_label_new ("<big>This is a long text that might need to be wrapped</big>");
  gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
  gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
  gtk_label_set_lines (GTK_LABEL (label), 3);

With this configuration, GtkLabel will automatically wrap lines to the right width and only ellipsize the last one, if needed:

three-lines-ellipsized.png

Ellipsized labels

Sometimes, it is convenient to only show as much of text as fits, and indicate that there is more by using an ellipsis (…). GtkLabel supports this with this property:

  GtkLabel::ellipsize: The preferred place to ellipsize the string

Setting it to a value other than the default PANGO_ELLIPSIZE_NONE enables ellipsization. For the usual ellipsization at the end, use PANGO_ELLIPSIZE_END.

Here is a gjs example showing a label with ellipsization turned on:

const Gtk = imports.gi.Gtk;
const Pango = imports.gi.Pango;

Gtk.init(null);

let win = new Gtk.Window({ type: Gtk.WindowType.TOPLEVEL });
let box = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL });

win.set_title("Window");
win.set_border_width(10);

let label = new Gtk.Label({ label: "This is a long text that might need to get ellipsized" });
label.set_ellipsize(Pango.EllipsizeMode.END);

win.add(box);
box.add(label);

win.show_all();
Gtk.main();

With this, the label will still come up like this:

ellip1.png

But it can be ellipsized all the way when the window is resized:

ellip2.png

Other ellipsization modes exist, e.g. with Pango.EllipsizationMode.MIDDLE, you get a result like this:

ellip5.png

To control how much of the label can be ellipsized away, use the width-chars property. After adding:

label.set_width_chars(15);

the window can only be shrunken some of the way:

ellip3.png

Note that the width-chars property is based on the average character with of the font, and thus the remaining text may not exactly be the number of characters you specified.

Even with this setting, the window will still come up with all the text visible, since the label claims the width of the entire content as its natural width. To make the label request less, use the max-width-chars property. With

label.set_max_width_chars(30);

the window will come up like this:

ellip4.png

HowDoI/Labels (last edited 2021-04-06 14:48:01 by MatthiasClasen)