It is fairly easy to add a custom datatip
f = figure();
plot( 1:100, sort(rand(100,1)) );
dc = datacursormode( f );
set( dc, 'UpdateFcn', @onDataCursorUpdate );
function txt = onDataCursorUpdate( tip, evt )
txt = {sprintf( 'X: %g', tip.Position(1) ), ...
sprintf( 'Y: %g', tip.Position(2) )};
end
But the update function might take a while to fetch the datatip info.
In my case, the data I want to include in txt
has to be fetched from a database query. I realise that this is inefficient from a performance standpoint, but it is much more memory efficient than storing all possible datatip attributes in memory!
function txt = onDataCursorUpdate( tip, evt )
info = mySlowQuery( tip.Position ); % fetch some data about this point
txt = {sprintf( 'X: %g', tip.Position(1) ), ...
sprintf( 'Y: %g', tip.Position(2) ), ...
sprintf( 'Info: %s', info )};
end
This query may take minutes(!), and unfortunately MATLAB updates the position of the datatip before updating the label, so you can end up with the following sequence of events:
Is there a way to prevent this happening, so there is no period when the label is incorrect?
You can directly interact with the datatip at the start of the callback to clear the label, then run the body of the callback. The output txt
still automatically gets assigned to the datatip String
property, but you can manually change it earlier in the function:
function txt = onDataCursorUpdate( tip, evt )
% Clear the string first, use "loading..." as placeholder text
txt = {sprintf( 'X: %g', tip.Position(1) ), ...
sprintf( 'Y: %g', tip.Position(2) ), ...
'Info: loading...'};
tip.String = txt;
% Now run the slow update
info = mySlowQuery( tip.Position ); % fetch some data about this point
txt = {sprintf( 'X: %g', tip.Position(1) ), ...
sprintf( 'Y: %g', tip.Position(2) ), ...
sprintf( 'Info: %s', info )};
end