PBToolboxAI v5 ← Site

angulargauge — u_pbt_angulargauge #

← Component reference · Guide contents

Dial: one value read on a circular scale — a needle, a filled arc or a marker on the rim, coloured ranges that say whether it is good, a target, a readout in the format of your choice.

▶ See it live — Demo application, Angular gauge tile: the preview, the code behind it and this page, side by side.


In brief #

Userobjectu_pbt_angulargauge
Item classn_pbt_angulargauge_range (of_range(key))
Used forReading a quantity at a glance — a speed, a temperature, how far a goal is reached, a thermostat knob
PrincipleYou give a scale, a value and ranges; the graduations, the numbers, the colours and the animation are ours
FamilyTwin of gauge: same methods, same events, and the same properties apart from the geometry — here the angles and the round ends, there the orientation and the placement of the ranges

Quick start #

// A scale from 0 to 240, a number every 20
uo_dial.id_maximum = 240
uo_dial.id_tick_step = 20

// Three ranges of the scale, each with the tone of what it means
uo_dial.of_add_range(/*key*/ "city", /*from*/ 0, /*to*/ 130)
uo_dial.of_add_range(/*key*/ "fast", /*from*/ 130, /*to*/ 180)
uo_dial.of_add_range(/*key*/ "limit", /*from*/ 180, /*to*/ 240)
uo_dial.of_range(/*key*/ "city").is_tone = u_pbt_angulargauge.TONE_SUCCESS
uo_dial.of_range(/*key*/ "fast").is_tone = u_pbt_angulargauge.TONE_WARN
uo_dial.of_range(/*key*/ "limit").is_tone = u_pbt_angulargauge.TONE_DANGER

// The unit, and the value : the needle turns to it
uo_dial.is_unit = "km/h"
uo_dial.id_value = 96

The scale, the value and the ranges #

The scale runs from id_minimum to id_maximum (0 to 100 by default). The value id_value reads back as you gave it: outside the scale it is drawn pegged at the nearest end and the readout still writes it — a gauge that silently rewrote what the application measured would lie twice. Set by the code it raises no event, like SetItem: ue_value_changed says what the user did. NULL is ignored: the previous value stays — test a measure that may be missing (GetItemNumber returns NULL) before you set it.

The numbers follow is_format, the display format of a DataWindow (#,##0.0, $#,##0, 0% writes the PART of the scale — 50 on 0..200 reads 25%, as the progress bar does), with the separators of the display language. Without a format, the scale chooses the decimals of the readout — two for a scale of 0 to 1, none for 0 to 100 —, never the value, which would write 43 one second and 42.55 the next; the numbers of the scale take those of their step.

A range colours a portion of the scale: its colour is the one you give, otherwise that of its tone (TONE_SUCCESS, TONE_WARN, TONE_DANGER, TONE_INFO = the theme accent, TONE_NEUTRAL — one set of colours per light or dark mode), otherwise that of the palette. Ranges overlap in the order they were added; of_current_range() says which one the value is in. Under a needle they are the band; under a filled arc, a ring inside it. A range holds its start but not its end: on the end two ranges share (60 between 0–60 and 60–85), the value is in the one that starts there, whatever the order of the adds; the end of the scale belongs to the range that reaches it. The palette colour of a range is fixed when it is added: removing one recolours no other. A range entirely outside the scale is not drawn.

Angles are counted in degrees, 0 at the top, clockwise: by default the scale starts at -135 (bottom left) and covers 270 degrees — a speedometer. ii_start_angle = -90 and ii_sweep_angle = 180 give a half dial, drawn twice as large. A dial is a measuring instrument: it does not turn round in a right-to-left application.


Properties #

PropertyTypeDefaultRole
is_titlestring""The title, above the dial. Markup accepted; it also names the component for a screen reader. Without a title, the plain text of the tooltip names it (is_super_tooltip_title, else is_tooltip), else the word “Gauge” in the display language
id_valuedouble0The value. It slides to its place; outside the scale, drawn pegged and read back as given. Set by the code, silent; NULL is ignored, the previous value stays
id_minimumdouble0The start of the scale. A scale whose minimum is not below its maximum is empty: no graduation, no number, no range, no pointer and no target, and of_current_range() gives an empty string. To turn a scale round, ib_reversed
id_maximumdouble100The end of the scale
is_formatstring""The display format of every number — readout, scale, ends of a range —, in the syntax of a DataWindow format (#,##0.00, $#,##0, 0%), separators of the display language. Empty = the readout takes the decimals of the scale (two for 0 to 1, none for 0 to 100), the numbers of the scale those of their step (0.0, 0.2… 1.0)
is_unitstring""Written after the value in the readout (%, km/h)
ib_show_valuebooleantrueShows the readout — the value and its unit — under the pivot of a needle (below the numbers of the two ends on a small dial), in the middle of a filled arc. Without it, a needle dial is drawn larger
id_tick_stepdouble0The step between two numbered graduations. 0 = chosen by the scale: a nice step (1, 2, 2.5 or 5 times a power of ten, then 3, 4.5 or 6) that falls on both ends when one does — 0 to 90 by 10, −50 to 50 by 25, 0 to 360 by 60 —, otherwise counted from the minimum (32 to 212 by 20). A step you give is always counted from the minimum; a step that would draw more than 200 graduations falls back on the automatic one. Each end carries a numbered graduation. When the numbers do not all fit, one in k is written so the step stays regular, and both ends are always written. The numbers take the decimals of their step. The step chosen is never finer than what is_format writes (0 to 3 at #,##0: 0, 1, 2, 3); a step you give stays yours, and the format rounds its numbers. On a dial too small for a circle of numbers none is written; on a small filled arc the readout moves to keep both ends
ii_minor_ticksinteger4Small graduations between two numbered ones (0 to 9)
ib_show_ticksbooleantrueShows the graduations
ib_show_labelsbooleantrueShows the numbers of the scale; on a dial too small for a circle of numbers none is written — the readout and the ranges still speak
id_targetdouble0A target — a goal, a threshold —, marked across the band while ib_show_target is true
ib_show_targetbooleanfalseShows the mark of id_target
is_pointerstringneedleHow the value is shown (constants POINTER_*): NEEDLE, a needle; BAR, the band filled from the minimum — a solid gauge, the number in the middle; MARKER, a triangle on the rim. Unknown = NEEDLE
il_value_colorlong-1The colour of the value — the needle, the filled arc or the marker; -1 = the theme accent
il_track_colorlong-1The colour of the band; -1 = a tint of the text colour of the theme
ii_thicknessinteger0The thickness of the band, in pixels (0 to 80, never more than half the radius); 0 = automatic: a share of the radius, kept between 6 and 24 px under a needle or a marker, between 8 and 36 px for a filled arc — a large dial stays a dial. The numbers of the scale (11 to 16 px) and the readout grow with it
ib_reversedbooleanfalseThe maximum at the start of the arc: the scale runs counter-clockwise. Right and Up still turn clockwise: on a reversed dial they lower the value
ii_start_angleinteger-135Where the scale starts, in degrees: 0 at the top, 90 on the right, -90 on the left (450 reads back 90)
ii_sweep_angleinteger270How much of the circle the scale covers, in degrees (10 to 360). A negative angle counts as its size: to make the scale run the other way, ib_reversed. The dial is fitted to the room that angle takes
ib_editablebooleanfalseThe user moves the value: turn the needle round the pivot, click the dial, arrows, Page Up / Down (ten steps), Home and End. A click near the pivot, on the readout or away from the dial (beyond the band and the marks beside it) sets nothing; during a drag the hand may leave the dial, the value stays at the end it comes from and never jumps across the gap. Right and Up turn clockwise, as a rotary knob, wherever the arc runs (on a reversed dial they lower the value). Each gesture raises ue_value_changed once — a key, like the hand, puts the value at once, and a drag cut short (a message box, Alt+Tab) ends like a release; Escape during a drag gives the value back (a value your code wrote meanwhile stays) without pressing the window's Cancel button; the Menu key names the range the value is in
id_stepdouble0The step of the hand and of the keys; 0 = the precision the readout shows (the decimals of is_format, or those the scale chooses): on a scale of 0 to 7 the hand gives 2.6, never a 2.61 the user did not read; a key moves by a hundredth of the scale, never less than one shown digit. Both ends stay reachable when the step does not divide the scale: from 0 to 100 by 30, the value goes 0, 30, 60, 90, 100
ib_track_dragbooleanfalseWith ib_editable, opt-in: while the user drags the value, ue_value_tracking follows the hand — a volume heard live, a preview redrawn. ue_value_changed still comes once, when the hand lets go; when a drag is cut short (Escape, ib_editable or ib_enabled set to false by the code), ue_value_tracking also says the value it started from
ib_value_tooltipbooleantrueThe panel that names the range under the pointer, with its ends. It is not is_tooltip, the tooltip of the whole component. The tooltip of a range (its is_tooltip) is written in this panel, even at false
ib_value_follows_rangebooleanfalseOpt-in: the value — the needle, the filled arc or the marker — takes the colour of the range it is in (the one drawn on top where two overlap): red in the red zone. Outside every range it keeps il_value_color, else the theme accent. While the value slides, the colour follows the value drawn
ib_roundedbooleanfalseOpt-in: round ends on the band, the filled arc and the ranges. Each one is shortened by half its width at both ends so that it stays on its part of the scale; a range shorter than its own width becomes a dot. A full circle keeps its band closed
ib_pointer_tooltipbooleanfalseOpt-in: the panel also names the value under the mouse — on the needle, the filled arc or the marker — and the target, with their number in the format of the readout. The ranges keep their own panel (ib_value_tooltip)
id_origindouble0Where the filled arc (POINTER_BAR) starts: a value below the origin fills the other way — a gap, a variance, a scale of −50 to 50 that starts at 0. Until it is set — or once set back to NULL — the arc starts at the minimum and the property reads the minimum; outside the scale, at the nearest end. The twin of id_origin of gauge
ib_auto_heightbooleanfalseThe component reports its ideal height and the userobject fits it (ue_auto_height). The width drives it: a half dial is half as tall
ib_enabledbooleantrueGreyed out, it keeps showing its value but stops answering: no click, no key, no drag, and it leaves the Tab order
ib_animatedbooleantrueThe value slides to its place, frame by frame — the needle turns —, and arrives from the start of the scale (its minimum) when the component is drawn. A setting changed during the slide (title, unit, colour, size) does not cut it. A workstation set to reduce motion never animates; the user's hand is never animated; a value set under of_set_redraw(false) slides when drawing resumes
ii_anim_durationinteger450Duration of the slide, in milliseconds (0 to 5000)
is_anim_easingstringease-outThe curve of the slide (constants EASING_*, the names of LiveCharts2): back-out goes past then comes back, bounce-out bounces, elastic-out snaps. An overshoot stays on the scale. Unknown = ease-out
is_theme_stylestring""Visual style of the component (THEME_STYLE_* constants); empty = the application's, followed at every change
is_theme_modestring""Light or dark variant (THEME_MODE_* constants); empty = the application's, followed at every change
il_theme_accentlong-1Accent colour of this component (-1 = the theme's accent)
is_tooltipstring""Plain tooltip shown when hovering the component
is_super_tooltip_titlestring""Title of the rich tooltip (takes precedence over is_tooltip)
is_super_tooltip_textstring""Text of the rich tooltip (rich markup accepted)
is_super_tooltip_imagestring""Image of the rich tooltip

Methods #

MethodRole
of_add_range ( string as_key, double ad_from, double ad_to { , long al_color } )Adds a coloured range from ad_from to ad_to (ends written backwards are drawn the right way round); the overload with a colour sets it, otherwise the tone then the palette. Returns 0 once added, -5 when the key is empty, holds / or `, or is already held (an add never replaces), -2` when the component is not created. The palette colour is given at the add: removing a range recolours no other one
of_clear_ranges ( )Removes every range — their handles go with them —, the value and the settings stay. Returns 0 once done, -2 when the component is not created
of_current_range ( )The key of the range the value is in right now, an empty string when it is in none or when the scale is empty. Where two ranges overlap, the last one added — the one drawn on top — wins. A hidden range is not counted; a range the demo mode does not draw is: what this reads never depends on the licence. A range holds its start but not its end: on the end two ranges share, the value is in the one that starts there, whatever the order of the adds; the end of the scale belongs to the range that reaches it. A range outside the scale (not drawn) counts too
of_range ( string as_key )The n_pbt_angulargauge_range handle of a range, to read or change its ends, colour, tone, name or visibility
of_remove_range ( string as_key )Removes one range; its handle is destroyed. Returns 0 once removed, -5 when no range has this key, -2 when the component is not created
of_reset ( )Empties the ranges — handles included — and puts every property back to its original value. Returns 0 once done, -2 when the component is not created

Events #

EventRaised when
ue_value_changed (double ad_value)With ib_editable only: the user has moved the value — once per drag (when the button is released, or when the drag is cut short: a message box opened under the hand, Alt+Tab), per click, per key. A value set by your code does not raise it, even during a drag. To follow the hand during the drag: ib_track_drag
ue_value_tracking (double ad_value)With ib_editable and ib_track_drag only, while the user drags the value: each new place of the hand, then — when the drag is cut short: Escape, or ib_editable / ib_enabled set to false by your code — the value it started from. The final value still comes once in ue_value_changed
ue_range_clicked (string as_key)A range was clicked — or confirmed with Enter or Space on the range the keyboard is on (Tab, then the arrows). Not on an editable component: a click there sets the value
ue_range_rclicked (string as_key, long al_x, long al_y)Right-click on a range, or the Menu key (Shift+F10) on the range the keyboard is on — on an editable component, the range the value is in: the place to open a menu; al_x, al_y: where to open the menu, in screen pixels — the pointer, or the middle of the range from the keyboard (Menu key, Shift+F10); a contextmenu opens there as they are (uo_menu.of_show(al_x, al_y))
ue_auto_height (long al_height)With ib_auto_height: the userobject has just been resized to its ideal height

Item properties #

A range is named by its key: uo_dial.of_range("warn").is_tone = u_pbt_angulargauge.TONE_WARN.

PropertyTypeDefaultRole
id_fromdouble0The start of the range, on the scale
id_todouble0Its end. Ends written backwards are drawn the right way round and read back as given
il_colorlong-1Its colour; -1 = that of its tone, otherwise of the palette. The inherited item colours (il_accent, il_back_color, il_text_color and their hover twins) have no effect on a range: il_color and is_tone decide
is_tonestring""Its tone (constants TONE_* of the component): SUCCESS, WARN, DANGER, INFO (the theme accent), NEUTRAL — one set per light or dark mode, any case understood. il_color wins; an unknown tone counts as no tone
is_labelstring""Its name, in the panel under the pointer and for a screen reader; empty = its key. Markup accepted
ib_visiblebooleantrueHides the range without removing it; like a check box, raises no event
is_tooltipstring""Its tooltip, written in the panel that names the range under the pointer — never a second bubble. Markup accepted
is_super_tooltip_titlestring""The bold title of its tooltip, written in the panel under its name
is_super_tooltip_textstring""The text of its tooltip, in the panel. Markup accepted
is_super_tooltip_imagestring""An image at the top of its tooltip, in the panel (bundle path, absolute path or resources.dll:name)

Examples #

A live dashboard #

// Timer event of the window : the needle turns to each new reading
uo_dial.id_value = ids_monitor.GetItemNumber(1, "speed")

// Which range is it in now ? An alert outside the good one
st_alert.visible = (uo_dial.of_current_range() <> "city")

A solid half gauge #

// The band fills from the minimum, the number in the middle
uo_dial.is_pointer = u_pbt_angulargauge.POINTER_BAR

// From the left, over half a circle : the upper half
uo_dial.ii_start_angle = -90
uo_dial.ii_sweep_angle = 180

// A scale from 0 to 1, written as a percentage
uo_dial.id_maximum = 1
uo_dial.is_format = "0%"
uo_dial.id_value = 0.72

A gap around zero #

// A scale centred on zero : the filled arc starts at 0, not at the minimum
uo_dial.is_pointer = u_pbt_angulargauge.POINTER_BAR
uo_dial.id_minimum = -50
uo_dial.id_maximum = 50
uo_dial.id_origin = 0

// Below the budget, the arc fills to the left of 0
uo_dial.id_value = -18

A value the user sets #

// The user moves the value, by steps of 5
uo_dial.ib_editable = true
uo_dial.id_step = 5

// Event ue_value_changed of uo_dial : apply what the user chose
ii_level = Integer(ad_value)

A volume set live #

// The user drags the value, and the sound follows the hand
uo_dial.ib_editable = true
uo_dial.ib_track_drag = true

// Event ue_value_tracking of uo_dial : the volume heard while the hand moves
inv_player.ii_volume = Integer(ad_value)

// Event ue_value_changed of uo_dial : the volume kept when the hand lets go
ii_saved_volume = Integer(ad_value)

A modern KPI #

// A filled arc with round ends, in the colour of the zone it is in
uo_dial.is_pointer = u_pbt_angulargauge.POINTER_BAR
uo_dial.ib_rounded = true
uo_dial.ib_value_follows_range = true

// The goal, and its number under the mouse
uo_dial.id_target = 85
uo_dial.ib_show_target = true
uo_dial.ib_pointer_tooltip = true
uo_dial.id_value = 74

A menu on a range #

// Event ue_range_rclicked of uo_dial : remember the range, then open the menu
// at the pointer of the window
is_menu_range = as_key
m_range.PopMenu(/*xlocation*/ w_main.PointerX(), /*ylocation*/ w_main.PointerY())

A picture of the dial for a report #

// The dial as it is on screen, title and readout included, to a PNG file
uo_dial.of_save_as_png(/*path*/ "C:\Reports\speed.png")

// The same, printed into a PDF file without any dialog
uo_dial.of_print_to_pdf(/*path*/ "C:\Reports\speed.pdf")

Good practice #


Inherited from the common base #

These members exist on every visual component — they are not specific to this one. They are detailed once, in the transverse chapters; this table only says where to read them.

MembersRoleDetailed in
of_count · of_keys_at · of_hasWalk what the component holds3.2 Items
of_resetPut the component back to zero3.6 Resetting a component: of_reset()
of_register_shortcut · of_clear_shortcutsThe component's keyboard chords3.5 Keyboard shortcuts
of_is_created · of_is_ready · of_get_last_errorWhether it was born, whether it is ready, what failed3.7 Diagnostics
of_save_as_png · of_save_as_jpgExport the rendering as an image3.8 Exporting the rendering as an image
of_set_redrawGroup changes into a single repaint3.10 Best practices
of_preload_iconsIcons shown with no delayInstant display: of_icon
of_set_translationTranslate one of the component's labels5.2 Adapting a label: of_set_translation
of_focus_webviewGive the component the focus6.4 Keyboard and focus
of_print · of_print_to_pdfPrint, or write a PDF6.9 Printing
of_set_property · of_get_property · of_component_nameDriving a property by its name3.1 The property engine
is_accessible_name · is_accessible_descriptionThe name and description a screen reader says3.4 Optional properties and events

Two helpers are not inherited: of_icon and of_escape_markup live on n_pbt_utils. Declare one — n_pbt_utils lnv_utils, nothing to create — and call them on it.

← Component reference · Guide contents