Is there a better way to initialize the DataTipTemplate field in primitive objects?
32 views (last 30 days)
Show older comments
Problem:
Creating a Chart Object as in Plot() initializes a DataTipTemplate field in the resulting handle.
p = plot(0,0);
p.DataTipTemplate % Does not return error
But creating the primitive handle directly does not, resulting in an error
q = line(0,0);
q.DataTipTemplate % Returns: "Unrecognized...'DataTipTemplate' for '...primitive.Line'"
mytip = datatip(q,1,1);
q.DataTipTemplate % Now is valid.
But this requires creating and deleting the datatip, which seems sub-optimal.
Ask:
Is there a better way to initialize the DataTipTemplate in primitive objects?
Context:
I'm trying to customize the datatip on a trisurf() plot, which returns a primitive "patch" handle with the same problem. Apparently trisurf() does not have the same initialization as something like plot() or scatter(). I'm also curious why this is...
0 Comments
Accepted Answer
Adam Danz
on 18 Nov 2021
Edited: Adam Danz
on 19 Nov 2021
I've had this problem with patch objects in the past and I solved it by doing something similar to what you suggested, making a temporary invisible datatip, setting DataTipTemplate, and then deleting the invisible datatip. It's fast and you don't see the temp datatip.
[x,y] = meshgrid(1:15,1:15);
z = peaks(15);
T = delaunay(x,y);
h = trisurf(T,x,y,z);
mytip = datatip(h,x(1),y(1),z(1),'Visible','off');
h.DataTipTemplate
delete(mytip)
Although it's not very closely related to this question, I've also used a ButtonDownFcn to place a datatip anywhere on a patch object rather than just at its coordinates (see here).
For whatever reason, the DataTipTemplate property is either not accessible or not even present in some objects until a datatip is added. I haven't had access to those classdef files to dig any deeper.
Custom datatip demo with trisurf
Data tip values can be based on a property of the object or can be manually defined but either of the two methods must be consistent for all rows of the datatip. By default, datatips use property values. For example, the first row of trisurf data tips use "XData".
Starting in R2021b you can assign values to UserData and use the propert value definition of datat tip values as follows
% Create trisurf
figure()
[x,y] = meshgrid(1:15,1:15);
z = peaks(15);
T = delaunay(x,y);
h = trisurf(T,x,y,z);
% Create labels, one for each XData
n = 3; %number of random characters
m = numel(h.XData); % number of labels
v = [65:90, 97:122]; % ASCII letters
labels = arrayfun(@(i){char(v(randi(numel(v), 1, n)))},1:m); % 1xn char vector
% Create datatip
dt = datatip(h,x(1),y(1),z(1));
% Assign new row to datatip
h.UserData = labels;
row = dataTipTextRow('Label', 'UserData');
h.DataTipTemplate.DataTipRows(end+1) = row;
Prior to R2021b you'll have to redefine all rows of the datatip to use custom values in additional rows,
% Create trisurf
figure()
[x,y] = meshgrid(1:15,1:15);
z = peaks(15);
T = delaunay(x,y);
h = trisurf(T,x,y,z);
% Create labels, one for each XData
n = 3; %number of random characters
m = numel(h.XData); % number of labels
v = [65:90, 97:122]; % ASCII letters
labels = arrayfun(@(i){char(v(randi(numel(v), 1, n)))},1:m); % 1xn char vector
% Create datatip
dt = datatip(h,x(1),y(1),z(1));
% Recreate datatip and add new row
s.DataTipTemplate.DataTipRows = [];
row1 = dataTipTextRow('X', h.XData(:), '%g');
row2 = dataTipTextRow('Y', h.YData(:), '%g');
row3 = dataTipTextRow('Z', h.ZData(:), '%g');
row4 = dataTipTextRow('Label', labels(:));
h.DataTipTemplate.DataTipRows = [row1; row1; row3; row4];
2 Comments
Adam Danz
on 19 Nov 2021
Ha! I thought I recognized your name!
I wonder what problems you had with the datatip function. It looks like you're using R2021a and that release also supports the z-coordinate (R2021a datatip documentation). In fact, I get an error using the version without the z coordinate,
mytip = datatip(h,x(1),y(1),'Visible','off'); % R2021b
Error using datatip (line 162)
Unknown property: 'off'.
This is because datatip is expecting the z coordinate but receives "visible" instead so it interprets "off" as a property name rather than a property value.
To add a new row for the datatip, you need to provide the value for all points in the object which is what the Matlab example is doing. The trisurf datatips are based on the X|Y|ZData so the number of labels needs to equal the number of data points.
I'll update my answer to include a demo.
Very nice overview of your file exchange submission.
More Answers (0)
See Also
Categories
Find more on Matrix Indexing 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!