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

3 vues (au cours des 30 derniers jours)
Matthias Firnkes
Matthias Firnkes le 5 Nov 2021
Commenté : Steven Lord le 15 Nov 2021
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 commentaire
per isakson
per isakson le 15 Nov 2021
The "code wells" of this question lack the the links Theme and Copy in the upper right corners.

Connectez-vous pour commenter.

Réponses (1)

per isakson
per isakson le 15 Nov 2021
Modifié(e) : per isakson le 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 commentaire
Steven Lord
Steven Lord le 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
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

Connectez-vous pour commenter.

Catégories

En savoir plus sur Graphics Object Programming dans Help Center et File Exchange

Produits


Version

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by