'line' returns number instead of handle inside a loop of a class method

조회 수: 3 (최근 30일)
Matthias Firnkes
Matthias Firnkes 2021년 11월 5일
댓글: Steven Lord 2021년 11월 15일
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
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
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
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
x = []
h = line(1:10, 1:10) % h is a Line handle
h =
Line with properties: Color: [0 0.4470 0.7410] LineStyle: '-' LineWidth: 0.5000 Marker: 'none' MarkerSize: 6 MarkerFaceColor: 'none' XData: [1 2 3 4 5 6 7 8 9 10] YData: [1 2 3 4 5 6 7 8 9 10] ZData: [1×0 double] Show all properties
x(end+1) = h % x(1) is the Line handle h converted to double
x = 10.0007
double(h)
ans = 10.0007
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 =
0×0 empty GraphicsPlaceholder array.
q(1) = h
q =
Line with properties: Color: [0 0.4470 0.7410] LineStyle: '-' LineWidth: 0.5000 Marker: 'none' MarkerSize: 6 MarkerFaceColor: 'none' XData: [1 2 3 4 5 6 7 8 9 10] YData: [1 2 3 4 5 6 7 8 9 10] ZData: [1×0 double] Show all properties

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Graphics Object Programming에 대해 자세히 알아보기

제품


릴리스

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by