'line' returns number instead of handle inside a loop of a class method
2 views (last 30 days)
Show older comments
I want to create a dynamic figure with a custom 'Plotter' class, linked to another custom object.
If I want to assign line handles to the Plotter object properties with a for loop, I get numbers instead of handle objects. I would like to understand why.
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/791054/image.jpeg)
As a simple example, I created a LinePlotter class:
classdef LinePlotter < dynamicprops
properties
fh
ah
lh
end
methods
function obj = LinePlotter(lines)
addlistener(lines,'ChangeParams',@obj.updatePlot)
obj.createBlankPlot()
end
function createBlankPlot(obj)
obj.fh = figure;
obj.ah = axes;
hold all;
% This gives a numeric output instead of handles...
for i = 1:4
obj.lh(i) = line([0,0],[0,0]); % only used to produce a line handle
end
% What would work:
% obj.lh = line([0,0],[0,0]);
% for i = 2:4
% obj.lh(i) = line([0,0],[0,0]);
% end
set(obj.lh(1), 'Tag','X1');
set(obj.lh(2), 'Tag','X2');
set(obj.lh(3), 'Tag','Y1');
set(obj.lh(4), 'Tag','Y2');
end
function updatePlot(obj,src,~)
z = 0:10;
y = src.slope.*z + src.offset;
set(obj.lh({obj.lh.Tag} == "X1"),'XData',z,'YData',y)
disp('plot updated')
end
end
end
For completeness the Line1 class:
classdef Lines1 < handle
properties
offset
slope
end
events
ChangeParams
end
methods
function obj = Lines1(o, s)
obj.offset = o;
obj.slope = s;
end
function NewParams(obj,varargin)
if nargin==2
obj.offset = varargin{1};
elseif nargin==3
obj.offset = varargin{1};
obj.slope = varargin{2};
end
notify(obj,'ChangeParams')
end
end
end
Even if there's a workaround to the problem, I would like to understand why the for loop 1:4 fails in creating line handles.
Interestingly, if I do the same outside a class definition, it works, e.g. :
for i = 1:4
test.lh(i) = line([0,0],[0,0]); % only used to produce a line handle
end
This creates a structure with 4 line handles, as expected.
Thanks for your help!
1 Comment
per isakson
on 15 Nov 2021
The "code wells" of this question lack the the links Theme and Copy in the upper right corners.
Answers (1)
per isakson
on 15 Nov 2021
Edited: per isakson
on 15 Nov 2021
I have reproduced your findings on R2018b.
The numerical "handles" are the old type, pre R2014b. I failed to find an explanation of the behavior in the documentation. "I would like to understand why the for loop 1:4 fails in creating line handles." I guess the reason is that Matlab isn't completely updated to HG2, the new graphic system.
Allocating the handles with
obj.lh = gobjects(4,1);
before the for-loop is a documented "work-around". Now I get
K>> obj
obj =
LinePlotter with properties:
fh: [1×1 Figure]
ah: [1×1 Axes]
lh: [4×1 Line]
K>>
1 Comment
Steven Lord
on 15 Nov 2021
I guess the reason is that Matlab isn't completely updated to HG2, the new graphic system.
No, that's not the reason for this behavior.
If you define a property, you can explicitly give it a default value or you can leave it to get a "default" default value. As stated in the Property Default Values section on this documentation page in the description of Prop1 "No assignment results in empty [] default value" Therefore when you try to assign a line handle into that property, it needs to be converted into the type of the empty default value [] (which is a double array.)
x = [] % x is double
h = line(1:10, 1:10) % h is a Line handle
x(end+1) = h % x(1) is the Line handle h converted to double
double(h)
When you indicated that the default value was the object array returned by gobjects you now fall into the case illustrated by Prop4. No conversion needs to happen to store a Line handle into a GraphicsPlaceholder array since it's a heterogeneous array.
q = gobjects(0)
q(1) = h
See Also
Categories
Find more on Graphics Object Programming in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!