picture — u_pbt_picture #
← Component reference · Guide contents
Image display: every common format, framing modes, alignment, automatic graying and a counter badge.
▶ See it live — Demo application, Picture tile: the preview, the code behind it and this page, side by side.
At a glance #
| Userobject | u_pbt_picture |
| Item class | — (component without items) |
| Used for | Replacing a PowerBuilder picture: modern formats (SVG, WebP, animated GIF), controlled framing, clickable image, automatic graying |
| Opt-in options | ib_track_mouse |
Quick start #
// window open event
uo_image.is_source = "img\logo.png"
uo_image.is_stretch = uo_image.STRETCH_UNIFORM // fits without distorting
uo_image.is_align = uo_image.ALIGN_CENTER
uo_image.is_tooltip = "Company logo"
Where the image comes from: is_source #
is_source accepts four forms, all interchangeable:
| Form | Example | Use |
|---|---|---|
| Local file | img\logo.png | png, jpg, jfif, bmp, gif, ico, svg, webp, avif |
| Web address | https://…/logo.png | Image loaded from a server (https only: an http:// address is refused, see below) |
| Embedded data | data:image/png;base64,… | Image already in memory, with no intermediate file |
| DLL resource | img\packimages.dll:SAMPLE | Image packaged in a resource DLL |
An anim: prefix can be placed in front of a GIF to explicitly flag an animation (GIFs animate anyway).
When the same name exists under several resource types in a DLL, state the type: img\packimages.dll:PNG/SAMPLE, SVG/SAMPLE, ICON/APP, RCDATA/BLOB. See Images and icons for the mono: and tint: prefixes, which recolor a glyph according to the theme.
An http:// address is refused: the component's page is secure, and the engine would silently switch the image to https:// — on an intranet server without TLS it would then fail with a misleading message. The component therefore refuses it up front: error glyph and ue_error with REASON_INSECURE. For an image on an unencrypted server, download it first with n_pbt_restclient.of_download into a temporary folder, then show that path. Setting the same path again reads the file again: an image your application has just rewritten (photo, scan, crop) shows up, as with the native Picture. An image on disk is limited to 32 MB.
How it is framed: is_stretch #
| Constant | Effect |
|---|---|
STRETCH_UNIFORM | Default. The image is scaled without distortion and stays fully visible; margins may appear |
STRETCH_UNIFORMTOFILL | Scaled without distortion, but the frame is filled completely; anything overflowing is cropped |
STRETCH_FILL | The image is stretched to fit the frame exactly — it may be distorted |
STRETCH_NONE | Original size, no scaling |
is_align decides the horizontal position of the image when it is smaller than the control: ALIGN_CENTER (default), ALIGN_START, ALIGN_END. The vertical axis has its own property, is_valign. The placement is read on screen: ALIGN_START stays on the leading edge whatever ii_rotation and ib_mirror. An unknown value reads back as center.
Constants #
| Constant | Value | For |
|---|---|---|
STRETCH_NONE · STRETCH_FILL · STRETCH_UNIFORM · STRETCH_UNIFORMTOFILL | "none" "fill" "uniform" "uniformtofill" | is_stretch |
ALIGN_CENTER · ALIGN_START · ALIGN_END | "center" "start" "end" | is_align |
VALIGN_TOP · VALIGN_CENTER · VALIGN_BOTTOM | "top" "center" "bottom" | is_valign |
ROTATION_NONE · ROTATION_90 · ROTATION_180 · ROTATION_270 | 0 90 180 270 | ii_rotation |
REASON_NOT_FOUND · REASON_TOO_LARGE · REASON_INSECURE · REASON_UNSUPPORTED · REASON_FAILED | "notfound" "toolarge" "insecure" "unsupported" "failed" | ue_error (as_reason) |
ALIGN_START and ALIGN_END are logical: they follow the writing direction (Language and RTL). The physical values left and right are still accepted as aliases.
Properties #
| Property | Type | Default | Purpose |
|---|---|---|---|
is_source | string | "" | The image to display (see the four forms above) |
is_stretch | string | "uniform" | Framing mode: STRETCH_NONE, STRETCH_FILL, STRETCH_UNIFORM, STRETCH_UNIFORMTOFILL |
is_align | string | "center" | Horizontal placement when the image is smaller than the control: ALIGN_CENTER, ALIGN_START, ALIGN_END. The vertical axis is is_valign |
is_valign | string | VALIGN_CENTER | Vertical placement when the image is smaller than the control: VALIGN_TOP, VALIGN_CENTER, VALIGN_BOTTOM. The two axes are independent — is_align gives the column, this one the row — which is what makes a corner reachable |
ib_enabled | boolean | true | When false, the image is displayed in grayscale and answers nothing: clicks, wheel, keyboard and file drops |
ii_badge | integer | 0 | Counter badge in the top corner at the end of the line: right in a left-to-right reading, left in a right-to-left one (0 = none) |
il_badge_color | long | -1 | Badge background, as a PowerBuilder RGB value (-1 = not set: the color that comes from the theme; 0 is black, like any other color). The text color is picked automatically so that the counter stays legible |
ii_badge_size | integer | 0 | Badge height in pixels (0 = the size that comes from the theme). The font size follows on its own: the counter stays centered whatever the size |
ib_track_mouse | boolean | false | Opt-in: enables ue_mouse_enter / ue_mouse_leave |
is_placeholder | string | "" | Stand-in image, shown while is_source is empty (an « add a photo » frame, a silhouette). Displayed dimmed: a stand-in is not the content, and it is never announced as a loaded image. Accepts the mono: prefix, which recolours a monochrome glyph with the theme |
is_error_source | string | "" | Fallback image when the source fails to load. Leave it empty and the component shows its own error glyph — never an empty box, which tells the user nothing while ue_error only travels to your code. Accepts the mono: prefix |
ii_rotation | integer | 0 | Quarter turns, for the scans and photos that arrive lying down: ROTATION_NONE, ROTATION_90, ROTATION_180, ROTATION_270 (anything else reads as 0). A quarter turn swaps the fitting axes as well, so the picture keeps its proportions instead of being squashed |
ib_mirror | boolean | false | Horizontal mirror on screen: the picture is flipped left to right, whatever ii_rotation |
ib_zoomable | boolean | false | Opt-in: the user may come closer (wheel, towards the pointer, or the + and - keys), move around (drag, or the arrows — inverted in a right-to-left reading) and go back to the fitted view (double click, or 0); the 1 key shows the picture at its ACTUAL size, one pixel of the picture for one pixel of the screen. Larger than its frame, the picture always covers it: a drag never uncovers an empty band; smaller, it stays where is_align and is_valign put it. Only the left button drags it. For a plan, a scan or a photo — where four fixed fitting modes are not enough |
id_zoom | double | 1.0 | Zoom factor: 1.0 is the framing chosen by is_stretch, up to id_max_zoom (8.0 by default). Reading it back gives the current factor, wheel and keyboard included (ue_zoom_changed tells you each change: a gesture of the user, or this property set by your code). Needs ib_zoomable, set first: without it the factor stays 1.0 |
id_max_zoom | double | 8.0 | The CEILING of the zoom, in the unit of id_zoom (1.0 = the fitted view): the wheel, the keys and id_zoom stop there. Any value from 1.0; under it, the default comes back. The ACTUAL size always stays reachable — the 1 key goes there, and a large scan shown small remains readable pixel for pixel. Lowered under the current zoom, the zoom comes down to it and ue_zoom_changed says so |
ib_allow_drop | boolean | false | Opt-in: accepts files dropped from the Windows Explorer. The frame shows it is armed, and the full paths arrive through ue_drop_files — loading them into is_source is up to your application. A disabled picture (ib_enabled = false) refuses every drop, and ib_allow_drop still reads back as set |
ib_auto_height | boolean | false | Opt-in: the userobject takes the height that keeps the image's proportions at its current width. For a picture that height is deducible: no need to compute it yourself from the dimensions reported by ue_loaded |
is_alt_text | string | "" | Text alternative: what a screen reader says of the picture. Leave it empty for a purely decorative picture |
is_theme_style | string | "" | Visual style of the component (THEME_STYLE_* constants); empty = the application's, followed at every change |
is_theme_mode | string | "" | Light or dark variant (THEME_MODE_* constants); empty = the application's, followed at every change |
il_theme_accent | long | -1 | Accent colour of this component (-1 = the application accent, or the theme's) |
is_tooltip | string | "" | Simple tooltip shown when hovering the component |
is_super_tooltip_title | string | "" | Title of the rich tooltip (takes precedence over is_tooltip) |
is_super_tooltip_text | string | "" | Text of the rich tooltip (rich markup accepted) |
is_super_tooltip_image | string | "" | Image of the rich tooltip |
Methods #
| Method | Purpose |
|---|---|
of_reset ( ) | Resets every property to its default and removes the image. Returns 0 once applied, -2 when the component is not created |
of_set_redraw (boolean) | Groups a burst of changes into a single render. Returns 0 once applied, -2 when the component is not created |
of_save_as_png (string) · of_save_as_jpg (string) | Exports the rendering as an image. Returns 0 once the image is written, -4 when writing fails, -2 when the component is not created |
Events #
| Event | Raised when |
|---|---|
ue_clicked ( ) | Left click on the image. Dragging the zoomed picture is not a click, and a double click raises only one, like the native Picture |
ue_loaded (long al_width, long al_height) | The image has loaded; the arguments carry its original size in pixels |
ue_error (string as_message, string as_reason) | The image could not be loaded. as_message names the source (image load failed : <source>), as_reason says why: REASON_NOT_FOUND (missing file), REASON_TOO_LARGE (over 32 MB), REASON_INSECURE (an http:// address, refused), REASON_UNSUPPORTED (a format the component does not show), REASON_FAILED (anything else: a file that does not decode, a server that does not answer) |
ue_rclicked ( ) | Right click on the image |
ue_double_clicked ( ) | Double click on the image. One ue_clicked comes before it, never two — like the native Picture. When ib_zoomable is on, the double click also brings the picture back to the fitted view: the event is raised either way, and what it means is up to you |
ue_zoom_changed (double ad_zoom) | The zoom factor changed: wheel, double click, the +, - and 0 keys, or id_zoom set by your code — nothing when the factor stays the same. 1.0 means back to the framing of is_stretch |
ue_auto_height (long al_height) | The component settled on a new height; the userobject has already been resized when this fires. Needs ib_auto_height |
ue_drop_files (string as_files[]) | Files dropped from the Explorer: full paths, one entry per file. Needs ib_allow_drop |
ue_drag_enter ( ) | A file drag entered the component (ib_allow_drop) |
ue_drag_leave ( ) | The file drag left the component |
ue_mouse_enter ( ) | The mouse enters — requires ib_track_mouse = true |
ue_mouse_leave ( ) | The mouse leaves — requires ib_track_mouse = true |
ue_ready ( ) | The component has finished loading; everything sent beforehand has been replayed |
ue_runtime_missing ( ) | The WebView2 runtime is missing: the component stays empty |
ue_bg_color (long al_color) | The component has computed its theme background color; the userobject has already adopted it (backcolor) |
Examples #
Showing the photo on a record #
// ue_row_changed event of the datawindow : show the photo of the current customer
uo_photo.is_source = "photos\" + ls_customer_code + ".jpg"
uo_photo.is_stretch = uo_photo.STRETCH_UNIFORMTOFILL // fills the frame, the overflow is cropped
uo_photo.is_align = uo_photo.ALIGN_CENTER
// ue_error event of uo_photo : (string as_message, string as_reason)
if as_reason = uo_photo.REASON_NOT_FOUND then
uo_photo.is_source = "img\photo_missing.svg" // fallback image
end if
Handling ue_error is the right way to deal with a missing photo: there is no need to test whether the file exists before assigning it.
A clickable image, button-style #
// The picture, and the tooltip shown when the mouse rests on it
uo_avatar.is_source = "photos\user.png"
uo_avatar.is_tooltip = "My account"
// ue_clicked event of uo_avatar
of_open_my_account()
Counter and graying #
// A notification badge on a mail icon
uo_mail.is_source = "img\packimages.dll:SVG/MAIL"
uo_mail.ii_badge = ll_unread // 0 makes the badge disappear
// Red beyond a threshold, theme color otherwise (-1)
if ll_unread > 20 then
uo_mail.il_badge_color = RGB(/*red*/ 200, /*green*/ 30, /*blue*/ 30)
else
uo_mail.il_badge_color = -1
end if
// Feature unavailable : the image turns grayscale, with no second image to supply
uo_mail.ib_enabled = ib_mail_allowed
Graying is computed automatically: you do not have to supply a second "disabled" image.
Finding out the real size of the image #
// Show the file the user has chosen
uo_preview.is_source = ls_chosen_file
// ue_loaded event of uo_preview : (long al_width, long al_height)
uo_status.of_panel(/*key*/ "main").is_text = String(al_width) + " x " + String(al_height) + " px"
// An image smaller than the frame : do not enlarge it needlessly
if al_width < uo_preview.width and al_height < uo_preview.height then
uo_preview.is_stretch = uo_preview.STRETCH_NONE
end if
A full-width banner #
// The banner image, filling its strip
uo_banner.is_source = "img\banniere.jpg"
uo_banner.is_stretch = uo_banner.STRETCH_UNIFORMTOFILL // fills the whole strip, without distorting
uo_banner.is_valign = uo_banner.VALIGN_TOP // keeps the top of the image visible
Best practices #
STRETCH_UNIFORMis the safe mode: it never distorts. SaveSTRETCH_FILLfor decorative backgrounds where distortion does not matter.- For a photo in a fixed frame (staff directory, thumbnail),
STRETCH_UNIFORMTOFILLgives a consistent result, with no unsightly margins. - Bundle your icons in a resource DLL rather than shipping hundreds of files; the
pack.dll:TYPE/NAMEform removes any ambiguity. - For a monochrome glyph that has to follow the light and dark themes, use the
mono:prefix (Images and icons). - Script
ue_erroron any image whose source depends on data: it is your only safety net when a file is missing. - Call
of_reset()before reusing the component for a different kind of image: otherwise the previous framing mode, badge or grayed-out state stays in place.
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.
| Members | Role | Detailed in |
|---|---|---|
of_reset | Put the component back to zero | 3.6 Resetting a component: of_reset() |
of_register_shortcut · of_clear_shortcuts | The component's keyboard chords | 3.5 Keyboard shortcuts |
of_is_created · of_is_ready · of_get_last_error | Whether it was born, whether it is ready, what failed | 3.7 Diagnostics |
of_save_as_png · of_save_as_jpg | Export the rendering as an image | 3.8 Exporting the rendering as an image |
of_set_redraw | Group changes into a single repaint | 3.10 Best practices |
of_preload_icons | Icons shown with no delay | Instant display: of_icon |
of_set_translation | Translate one of the component's labels | 5.2 Adapting a label: of_set_translation |
of_focus_webview | Give the component the focus | 6.4 Keyboard and focus |
of_print · of_print_to_pdf | Print, or write a PDF | 6.9 Printing |
of_set_property · of_get_property · of_component_name | Driving a property by its name | 3.1 The property engine |
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.