Table of Contents

Showing a value on an LED bar

TTMSFNCWidgetLEDBar renders a horizontal row of discrete LED segments and lights the first N of them, where N is the control's Value. It is the right control when a reading is best communicated as a segmented strip rather than a continuous fill or a numeric label: audio level meters, battery and signal-strength indicators, capacity bars, and step counters all read naturally as "how many LEDs are lit". Reach for TTMSFNCWidgetGauge instead when you need a circular dial with a needle, or TTMSFNCWidgetProgress when a smooth continuous bar fits better than discrete steps.

This chapter covers the core display loop: building the segment collection, spacing the LEDs, and driving the lit count from a value.

LED bar with ten segments and seven lit in a green-amber-red zone layout LED bar with ten segments and seven lit in a green-amber-red zone layout, dark theme

How the value maps to LEDs

The bar holds a collection of LED segments in its Leds property. The control's Value is an integer count of lit LEDs, counting from the left edge — it is not a percentage and not a scaled measurement. Assigning Value is clamped to the range 0..Leds.Count and updates the State of every segment so the first Value LEDs are lit and the rest are off. There is no Min/Max range and no orientation property: the strip is always drawn horizontally and sized to its bounds.

Because Value counts segments, decide your resolution by how many LEDs you add. Ten LEDs give you steps of 10%; twenty LEDs give you steps of 5%. Convert a raw reading to a lit count before assigning it, for example Bar.Value := Round(Percent / 100 * Bar.Leds.Count).

Build the bar and light segments

Create the control, populate the Leds collection (each entry is one LED), set Spacing for the gap between segments, then assign Value. Wrap collection edits in BeginUpdate/EndUpdate so the bar repaints once.

procedure TForm1.SetupLEDBar;
var
  I: Integer;
begin
  FBar := TTMSFNCWidgetLEDBar.Create(Self);
  FBar.Parent := Self;
  FBar.SetBounds(20, 20, 280, 48);

  // Size the segment collection. Each Leds entry is one LED.
  FBar.Leds.BeginUpdate;
  try
    FBar.Leds.Clear;
    for I := 0 to 9 do
      FBar.Leds.Add;
  finally
    FBar.Leds.EndUpdate;
  end;

  // Gap in pixels between LEDs and at the bar edges.
  FBar.Spacing := 6;

  // Value is the COUNT of lit LEDs, counting from the left (0..Leds.Count).
  // Setting it updates the State of every LED automatically.
  FBar.Value := 7;
end;

Spacing is the gap in pixels between adjacent LEDs and at the two edges of the bar; it defaults to 5 and is scaled automatically when the display DPI changes. The LEDs themselves are sized to fill the remaining width evenly, so a wider control or fewer segments produces larger LEDs.

Pitfalls

  • Value is a count, not a percentage or a scaled value. Bar.Value := 65 on a ten-LED bar lights all ten (the value is clamped to Leds.Count), it does not light 65%. Convert your reading to a segment count first.
  • There is no Count, Min, or Max published property. To change how many LEDs the bar has, add or remove entries in the Leds collection (or call InitSample for the default six). Older scaffold text referencing Min/Max is wrong for this control.
  • There is no orientation property. The bar always draws horizontally. Use the control's Width/Height bounds to shape it.
  • Edit the collection inside BeginUpdate/EndUpdate. Adding LEDs one at a time without it triggers a repaint per item.

See also