'line' returns number instead of handle inside a loop of a class method
조회 수: 3 (최근 30일)
이전 댓글 표시
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.
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
per isakson
2021년 11월 15일
The "code wells" of this question lack the the links Theme and Copy in the upper right corners.
답변 (1개)
per isakson
2021년 11월 15일
편집: per isakson
2021년 11월 15일
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
Steven Lord
2021년 11월 15일
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
참고 항목
카테고리
Help Center 및 File Exchange에서 Graphics Object Programming에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!