App Desinger: How to access Labels/Spinners via "Tags" in a custom UI component?

46 次查看(过去 30 天)
I have a modularized App Designer app with several custom UI components. One UI component is a setting for units (e.g. km/h - mph or deg - radiant). These settings should be applied to all other custom UI components. To reduce the implementation work I wan't a generic solution like:
  1. User changed the setting from "rad" toi "deg"
  2. all custom UI components get notified and get the changed data
  3. in the components should be a function with updates all Labels tagged with "LabelUnitAngle" from "rad" to "deg"
The non-generic solution is already working: comp.WheelAngleunitLabel.Text=comp.appSettings.units.angle.text;
comp.WheelAngleSpinner.Value = comp.ParamStore.WheelAngle*comp.appSettings.units.angle.factor;
I tried findall and findobj and tried using metaclasses but still no luck.
  2 个评论
dpb
dpb 2025-11-27,15:31
It would undoubtedly help if you could post the startup code section that creates the components in question.
Can you find the app uifigure itself programmatically, first, just for starters?
Have you tried passing the UIFigure handle as the object tree starting point in findall(), etc., ...?
Walter
Walter 2025-11-28,6:35
Thanks @dpb that you would like to help me. Without a meta class it was not possible for me. I finally found a solution:
function updateElementsByTags(comp)
%UPDATEELEMENTSBYTAGS Update UI labels in this component based on Tag values.
%
% This method scans all private, transient, non-copyable graphics
% properties of the component and updates their Text property
% depending on the Tag value. The unit strings are taken from
% comp.appSettings.units.*.text.
% Get only the UI handles (graphics objects); we ignore the names here
[~, handles] = getPrivateUiComponents(comp);
for k = 1:numel(handles)
h = handles(k);
% Safety check: only process objects that actually have Tag and Text
if ~isprop(h, "Tag") || ~isprop(h, "Text")
continue;
end
% Use the Tag to decide which unit text to apply
switch string(h.Tag)
case "TagUnitAngle"
h.Text = comp.appSettings.units.angle.text;
case "TagUnitVelocity"
h.Text = comp.appSettings.units.velocity.text;
case "TagUnitYawRate"
h.Text = comp.appSettings.units.yawrate.text;
case "TagUnitLength"
h.Text = comp.appSettings.units.length.text;
case "TagUnitAcceleration"
h.Text = comp.appSettings.units.acceleration.text;
otherwise
% Ignore all other tags
end
end
function [names, handles] = getPrivateUiComponents(obj)
%GETPRIVATEUICOMPONENTS Return private transient graphics properties.
%
% [NAMES, HANDLES] = GETPRIVATEUICOMPONENTS(OBJ) inspects the
% metaclass of OBJ, selects properties that are:
% - private
% - Transient
% - NonCopyable
% - not Constant
% - not Dependent
%
% For each of these properties, the current value is read. If the
% value is a graphics object (or array of graphics objects),
% they are collected into HANDLES. NAMES returns the corresponding
% property names.
% Get metaclass information
mc = metaclass(obj);
plist = mc.PropertyList; % array of matlab.metadata.Property objects
% Select only UI-related properties based on their metadata
isUiProp = arrayfun(@(p) ...
strcmp(p.GetAccess, "private") && ...
p.Transient && ...
p.NonCopyable && ...
~p.Constant && ...
~p.Dependent, ...
plist);
plist = plist(isUiProp);
% Collect names
names = {plist.Name};
% Initialize empty array of graphics handles
handles = gobjects(0);
% Read property values and keep only graphics objects
for k = 1:numel(names)
v = obj.(names{k});
% v may be a scalar handle, an array of handles, or something else
if isgraphics(v)
% Ensure we treat v as a column vector of handles
handles(end+1:end+numel(v)) = v(:); %#ok<AGROW>
end
end
end
end

请先登录,再进行评论。

回答(1 个)

Mario Malic
Mario Malic 2025-11-29,11:18
移动:Image Analyst 2025-11-29,23:27
Just thinking out here, wouldn't you want an each component to have an internal method that changes values/labels/anything that relates to the selected unit?
Create an event in your main component and make it trigger when the unit is changed (user interaction). Subscribe your other components to it and fire up the internal event to change units.
  4 个评论
Walter
Walter 2025-12-1,6:20
I have a listener to appSettingsChanged and an event that changes the units. My question is more for the next step. How to make the event generic? The background is that I want to make an UIcomponent template. The developers should not think about adding code to the event if they add a new spinner+label (they should only tag them).
Mario Malic
Mario Malic 2025-12-2,7:41
编辑:Mario Malic 2025-12-2,7:42
i see what you mean. i think, that, if you add Tags to the UI component, you would need to give devs a clear instruction how to do it. For example, if you have an Edit Field and Label component that are paired up to display the physical quantity you want to show. Then you would tag them as Quantity_1 and Value_1, then you would do something similar for all components that you want to use to show the values. This is a quick solution, but it works. You can search components within the UIFigure by Tags property to find the components you have given tag to, check findall function.
I don't know how difficult this is since I haven't played with custom components, but, what if you actually add a extend the default UI components to account for units? For example, to add logic for units and values in the combo box that is mentioned above.

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Create Custom UI Components 的更多信息

产品


版本

R2024b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by