- Undocumented Matlab - https://undocumentedmatlab.com -

Controlling plot data-tips

Posted By Yair Altman On September 14, 2011 | 82 Comments

Plot data tips [1] are a great visualization aid for Matlab plots. They enable users to interactively click on a plot location and see a tool-tip that contains the clicked location’s coordinates. The displayed tooltip text is even customizable using documented properties of the datacursormode [2] object.

plot data tips
plot data tips

A client has recently asked me to automatically display an attached data-tip to the last data point of a plotted time series of values. The idea was to immediately see what the latest value of the data series is.
Unfortunately, the official documentation clearly says that:

You place data tips only by clicking data objects on graphs. You cannot place them programmatically (by executing code to position a data cursor).

Well, this has never stopped us before, has it?

Creating new data tips

Under the hood, data tips use a data-cursor mode, which shares many similarities in behavior and programming code with the other plot modes (zoom, pan, data-brushing [3], etc.). At any one time, only a single such mode can be active in any figure window (this is a known limitation of the design). The code itself it actually quite complex and handles numerous edge-cases. Understanding it by simply reading the code (under %matlabroot%\toolbox\matlab\graphics\) is actually pretty difficult. A much easier way to understand the programming flow is to liberally distribute breakpoints (start in datacursormode.m) and interactively activate the functionality, then debug the code step-by-step.
Luckily, it turns out that the code to create a new data-tip is actually quite simple: first get the data-cursor mode object, then create a new data tip using the mode’s createDatatip() method, update some data-tip properties and finally update the data-tip’s position:

% First plot the data
hLine = plot(xdata, ydata);
% First get the figure's data-cursor mode, activate it, and set some of its properties
cursorMode = datacursormode(gcf);
set(cursorMode, 'enable','on', 'UpdateFcn',@setDataTipTxt);
% Note: the optional @setDataTipTxt is used to customize the data-tip's content text
% Note: the following code was adapted from %matlabroot%\toolbox\matlab\graphics\datacursormode.m
% Create a new data tip
hTarget = handle(hLine);
hDatatip = cursorMode.createDatatip(hTarget);
% Create a copy of the context menu for the datatip:
set(hDatatip,'UIContextMenu',get(cursorMode,'UIContextMenu'));
set(hDatatip,'HandleVisibility','off');
set(hDatatip,'Host',hTarget);
set(hDatatip,'ViewStyle','datatip');
% Set the data-tip orientation to top-right rather than auto
set(hDatatip,'OrientationMode','manual');
set(hDatatip,'Orientation','top-right');
% Update the datatip marker appearance
set(hDatatip, 'MarkerSize',5, 'MarkerFaceColor','none', ...
              'MarkerEdgeColor','k', 'Marker','o', 'HitTest','off');
% Move the datatip to the right-most data vertex point
position = [xdata(end),ydata(end),1; xdata(end),ydata(end),-1];
update(hDatatip, position);

Note: If you don’t like messing with the code, consider using Tim Farajian’s MakeDataTip [4] utility, which basically does all this behind the scenes. It is much easier to use as a stand-alone utility, although it does not give you the flexiblility with all the data-tip properties as in the code above.

Updating an existing data tip

To modify the appearance of a data-tip, we first need to get access to the hDatatip object that we created earlier, either programmatically, or interactively (or both). Since we can access pre-stored handles only of programmatically-created (not interactively-created) data-tips, we need to use a different method. There are actually two ways to do this:
The basic way is to search the relevant axes for objects that have Tag=’DataTipMarker’. For each data-tip, we will get two such handles: one for the marker (Type=’line’) and the other for the text box tooltip (Type=’text’). We can use these to update (for example) the marker size, color and style; and the text’s font, border and colors.
A better way is to access the graphics.datatip object itself. This can be done using two hidden properties of the datacursormode object:

% Get the list of all data-tips in the current figure
>> cursorMode = datacursormode(gcf)
cursorMode =
	graphics.datacursormanager
>> cursorMode.DataCursors
ans =
	graphics.datatip: 2-by-1
>> cursorMode.CurrentDataCursor
ans =
	graphics.datatip
>> cursorMode.CurrentDataCursor.get
            Annotation: [1x1 hg.Annotation]
           DisplayName: ''
           HitTestArea: 'off'
          BeingDeleted: 'off'
         ButtonDownFcn: []
              Children: [2x1 double]
              Clipping: 'on'
             CreateFcn: []
             DeleteFcn: []
            BusyAction: 'queue'
      HandleVisibility: 'off'
               HitTest: 'off'
         Interruptible: 'on'
                Parent: 492.005493164063
    SelectionHighlight: 'on'
                   Tag: ''
                  Type: 'hggroup'
              UserData: []
              Selected: 'off'
             FontAngle: 'normal'
              FontName: 'Helvetica'
              FontSize: 8
             FontUnits: 'points'
            FontWeight: 'normal'
             EdgeColor: [0.8 0.8 0.8]
       BackgroundColor: [1 1 0.933333333333333]
             TextColor: [0 0 0]
                Marker: 'o'
            MarkerSize: 5
       MarkerEdgeColor: 'k'
       MarkerFaceColor: 'none'
       MarkerEraseMode: 'normal'
             Draggable: 'on'
                String: {'Date: 01/09/11'  'Value: 573.24'}
               Visible: 'on'
             StringFcn: []
             UpdateFcn: []
         UIContextMenu: [1x1 uicontextmenu]
                  Host: [1x1 graph2d.lineseries]
           Interpolate: 'off'

We can see that the returned graphics.datatip object includes properties of both the text-box and the marker, making it easy to modify. Moreover, we can use its aforementioned update method to move the datatip to a different plot position (see example in the code above). In addition, we can also use the self-explanatory getCursorInfo(), getaxes(), makeCurrent(), movetofront() methods, and a few others.

Cursor mode and data-tip properties

The graphics.datacursormanager and the graphics.datatip objects have several public properties that we can use:

>> cursorMode.get
              Enable: 'off'
    SnapToDataVertex: 'on'
        DisplayStyle: 'datatip'
           UpdateFcn: @setDataTipTxt
              Figure: [1x1 figure]
>> cursorMode.CurrentDataCursor.get
            Annotation: [1x1 hg.Annotation]
           DisplayName: ''
           HitTestArea: 'off'
      ... % See the list above

Both these objects have plenty of additional hidden properties. You can inspect them using my uiinspect utility [5]. Here is a brief list for reference (R2011b):
graphics.datacursormanager:

  • CurrentDataCursor
  • DataCursors
  • Debug
  • DefaultExportVarName
  • DefaultPanelPosition
  • EnableAxesStacking
  • EnableZStacking
  • ExternalListeners
  • HiddenUpdateFcn
  • NewDataCursorOnClick
  • OriginalRenderer
  • OriginalRendererMode
  • PanelDatatipHandle
  • PanelHandle
  • PanelTextHandle
  • UIContextMenu
  • UIState
  • ZStackMinimum

graphics.datatip:

  • ALimInclude
  • ApplicationData
  • Behavior
  • CLimInclude
  • DataCursorHandle
  • DataManagerHandle
  • Debug
  • DoThrowStartDragEvent
  • EmptyArgUpdateFcn
  • EnableAxesStacking
  • EnableZStacking
  • EraseMode
  • EventObject
  • ExternalListenerHandles
  • HelpTopicKey
  • HostAxes
  • HostListenerHandles
  • IncludeRenderer
  • Invalid
  • IsDeserializing
  • MarkerHandle
  • MarkerHandleButtonDownFcn
  • Orientation
  • OrientationMode
  • OrientationPropertyListener
  • OriginalDoubleBufferState
  • PixelBounds
  • PointsOffset
  • Position
  • SelfListenerHandles
  • Serializable
  • TextBoxHandle
  • TextBoxHandleButtonDownFcn
  • Version
  • ViewStyle
  • XLimInclude
  • YLimInclude
  • ZLimInclude
  • ZStackMinimum
  • uistate

As can be seen, if we really want, we can always use the MarkerHandle or TextBoxHandle directly.

Deleting data tips

To delete a specific data-tip, simply call the cursor mode’s removeDataCursor() method; to delete all data-tips, call its removeAllDataCursors() method:

% Delete the current data-tip
cursorMode.removeDataCursor(cursorMode.CurrentDataCursor)
% Delete all data-tips
cursorMode.removeAllDataCursors()

Have you used plot data-tips in some nifty way? If so, please share your experience in a comment [6] below.
p.s. – did you notice that Java was not mentioned anywhere above? Mode managers use pure-Matlab functionality.

Categories: Handle graphics, Hidden property, Medium risk of breaking in future versions, Stock Matlab function, Undocumented feature, Undocumented function


82 Comments (Open | Close)

82 Comments To "Controlling plot data-tips"

#1 Comment By Isaac On September 15, 2011 @ 07:31

I have used programmable datatips to pull various extrema and their time hacks off a telemetry stream during V&V of flight software. It is VERY useful. I did not know about the other properties you’ve shown above — very cool. Thanks!

#2 Comment By Dani On July 11, 2012 @ 07:03

Hi Isaac! I just arrived to this post ,and what a surprise, because I use all this tips for flight test software aswell (data processing of flight parameters)!! He he he we all arrive to the same places…. [13] XD

Amazing work Mr. Altman by the way!!

#3 Comment By K On November 16, 2011 @ 10:21

Hi,

Thanks very much for this useful article!

I have a small problem I was hoping you can help me resolve. When I use your code above, the datatip is displayed in the right location on the curve, but instead of having the X and Y values, it contains a message that says “Error in datacursor datatip string function”. I tried updating the “String” field of hDatatip, but that doesn’t seem to help.

I would really appreciate any suggestions!

Thank you,
K

#4 Comment By Yair Altman On November 16, 2011 @ 10:38

@K – you need to change the data-cursor object’s UpdateFcn property to a custom text-update function handle, as described [14]. See the top code snippet on this page for an example of setting the property, and look at the link in the previous sentence for an explanation of the actual callback function.

Also see this related article: [15]

#5 Comment By K On November 16, 2011 @ 11:09

Thank you very much, Yair! 🙂

#6 Comment By Dènis Riedijk On December 25, 2011 @ 09:05

I have used this as a custom tooltip for a patch object. (Depending on position above the patch, a different tooltip needs to be displayed)
Just initialise the hDataTip hidden and without a cursor and set a timer for making it visible (and reset the timer in a windowbuttonmotionfcn so it displays after your mouse hovers for a certain amount of seconds)

cursorMode = datacursormode(figureHandle);
set(cursorMode, 'UpdateFcn',@setDataTipTxt, 'SnapToDataVertex', 'off', 'NewDataCursorOnClick',false);
hDatatip = cursorMode.createDatatip(handle(patchHandle));
set(hDatatip,'Host',handle(patchHandle), 'ViewStyle','datatip','OrientationMode','manual','Orientation','top-right');
set(hDatatip, 'MarkerFaceColor','none', 'MarkerEdgeColor','none', 'HitTest','off', 'Visible', 'off');

To use this as a tooltip, you might need to additionally do the following to make sure your clicks arrive at the right object and not at the datacursor or textbox:

set(0,'ShowHiddenHandles', 'on');
set(get(hDatatip,'Children'), 'HitTest','off'); % Otherwise our clicks end up in the default callbacks of data-tips.
set(0,'ShowHiddenHandles', 'off');

#7 Comment By John On December 29, 2011 @ 10:25

Great tip, thanks a lot! The following line doesn’t seem to work in Matlab r2011b, but removing it works just fine:

set(cursorMode, 'enable','on', 'UpdateFcn',@setDataTipTxt, 'NewDataCursorOnClick',false);

I used it to find and mark phase and gain margin on a Bode plot.

#8 Comment By Felipe On August 23, 2012 @ 11:49

Hello,
How can I pass a third argument to @setDataTipTxt?

I have a graph with several plots, each of them comes from a different source file. I want the datatip to tell me (X,Y) plus the name of the source file. For that reason, I was willing to pass a third argument with the name of the source file. Am I on the right way?

great blog.
thank you.

#9 Comment By Yair Altman On August 23, 2012 @ 12:56

@Felipe – you can do it like this:

set(cursorMode, 'UpdateFcn',{@setDataTipTxt,sourceFilename});

#10 Comment By Felipe On August 23, 2012 @ 13:49

@Yair, thanks for your answer.

I’d tried what you told me, but it seems there is a problem when appending sourceFilename to the output cell array of @setDataTipTxt. I’ve tried several ways but always get the same message: “Error in custom datatip string function”.

Do you have any idea why this is happening?

Thanks again.

#11 Comment By Yair Altman On August 23, 2012 @ 17:17

It means that you have an error in your setDataTipTxt function. Put a breakpoint there (or a try-catch block) to see exactly where and why.

#12 Comment By Felipe On August 24, 2012 @ 06:18

Hi Jair,

I believe my setDataTipTxt function is OK, I made it in the same way as it is explained in this blog:

[16]

I even made the same experiment (changing ‘Y’ for ‘$’) and everything seems fine. The problem begins when I try to append sourceFilename to the cell array output of setDataTipTxt

Do you have any idea why this may be happening? do you know any other turnaround?

Thanks a lot for your help.

#13 Comment By Yair Altman On August 25, 2012 @ 12:25

@Felipe – you probably forgot to declare the extra parameter(s) properly. See [17].

#14 Comment By Apn On November 30, 2012 @ 02:20

Hello Yair,

I’m new to matlab so this is likely to be a very basic question but I haven’t been able to find an answer so far. Maybe you can help.

The question is: How can I make a datatip display full integer value?

My X values are in the range 0 to 1500000
When I make a datatip it displays:
X: 3.669e+05
Y: 17

I would like it to be:
X: 366915
Y: 17

Is that possible?

Any help will be appreciated.

Thanks

#15 Comment By Yair Altman On November 30, 2012 @ 03:35

@Apn – of course it is possible. You just need to create a custom UpdateFcn for the figure’s [18]:

cursorMode = datacursormode(gcf);
datacursormode on;
set(cursorMode,'UpdateFcn',@myDataTip)

where myDataTip is defined as follows:

function text_to_display = myDataTip(cursorMode,eventData)
   pos = get(eventData,'Position');
   text_to_display = {['X: ',num2str(pos(1))], ...
                      ['Y: ',num2str(pos(2))]};
end

More examples:

* [19]
* [20]
* [16]

(looks like this is a favorite topic for Doug… 🙂 )

#16 Comment By Apn On December 3, 2012 @ 01:55

@Yair – Thanks, just what I was looking for.

BTW:
There is a small problem with the example, I think.
A ) is missing in line 3 of the function.
But besides that it worked perfectly.

Thanks again.

#17 Pingback By Handle Graphics Behavior | Undocumented Matlab On March 6, 2013 @ 14:24

[…] HG handles for displaying a plot data-tip (a.k.a. data cursor). I have explained in the past how to programmatically control data-tips, but doing so relies on the figure datacursormode, which is figure-wide […]

#18 Comment By Dani On April 20, 2013 @ 22:03

Hi Yair,
First off, I’m fairly new to Matlab but I love your blog – its super informative and I’m looking forward to getting more practice so I can appreciate it more!
I was hoping you could help me with a minor predicament. I’m using the data cursor for its point selection property but would rather the textbox not be displayed at all. I’ve tried almost everything, including suppressing it in the updateFcn callback using:

function output_txt = getRidofTextBox(obj,event_obj, datapointhandle)
h = get(datapointhandle, 'DataCursors');
j = get(h, 'TextBoxHandle');
set(j, 'Visible', 'off');

but this doesn’t work, since it would appear the property just gets reset in a later callback. I’m running out of ideas and was hoping you would be able to point me in the right direction.
Thanks!

#19 Comment By Yair Altman On April 20, 2013 @ 23:56

@Dani – try setting the output_txt to ” (empty), and datapointhandle.CurrentDataCursor‘s BackgroundColor and EdgeColor properties to ‘w’ (or rather, to your axes’ BackgroundColor)

#20 Comment By Dani On April 21, 2013 @ 11:56

@Yair
Thanks for looking into it! Unfortunately I’ve tried the empty string and I either get the warning ‘Error in custom datatip string function’, or it defaults back to a previous allowable value. Switching the box to white also doesn’t solve the problem since its still displayed on top of the plot – unless I misunderstood your advice. Thanks anyways!

#21 Comment By Yair Altman On April 21, 2013 @ 11:59

@Dani – an error means that you have some Matlab error in your callback function, and then Matlab automatically defaults back to the default. Anyway, if an empty string is not allowed, you can always try a sting containing a single space character. The data-tip box will then be so small that the obstruction of the plot data will probably be unnoticed.

#22 Comment By Ben On July 15, 2013 @ 21:46

What is the proper way to create a datatip in window (instead of datatip) mode programmatically?

I’ve tried this function based on your code and it works except I get tooltips instead of data in the window:

 
function hDatatip = CustomDataTip(hObj, index, callbackhand)
    cursorMode = datacursormode(ancestor(hObj, 'figure'));
    
    % enable datatips
    datacursormode on;
    set(cursorMode, 'updatefcn', callbackhand);
    set(cursorMode, 'NewDataCursorOnClick', false);
    set(cursorMode, 'DisplayStyle', 'window');
    
    % Delete all data-tips
    cursorMode.removeAllDataCursors();
    
    hDatatip = createDatatip(cursorMode, hObj);
    
    % adjust properties
    set(hDatatip, 'UIContextMenu', get(cursorMode, 'UIContextMenu'));
    set(hDatatip, 'HandleVisibility', 'off');
    set(hDatatip, 'Host', hObj);
    set(cursorMode, 'DisplayStyle', 'window');
    %set(get(hDatatip,'TextBoxHandle'), 'Visible', 'off');
    
    % create datatip
    xData = get(hObj, 'XData');
    yData = get(hObj, 'YData');
    pos = [xData(index) yData(index)];
    set(get(hDatatip, 'DataCursor'), 'DataIndex', index, 'TargetPoint', pos);
    set(hDatatip, 'Position', pos);
    updateDataCursors(cursorMode);
end

#23 Comment By Ben On July 16, 2013 @ 11:25

Hi, I just figured I’d report back, I think I figured it out (please excuse the ugly code, I’m sure this can be made much cleaner, but it seems to work). All off the functions called I simply stole verbatim from datacursormode.m and pasted into the same file as this function.

function hDatatip = CustomDataTip(hObj, index, callbackhand) 
    cursorMode = datacursormode(ancestor(hObj, 'figure'));
    hMode = getuimode(ancestor(hObj, 'figure'), 'Exploration.Datacursor');
    hTool = localGetObj(hMode);
    
    % enable datatips
    set(cursorMode, 'enable','on', 'UpdateFcn',callbackhand, 'NewDataCursorOnClick',false);
    
    % Delete all data-tips
    cursorMode.removeAllDataCursors();
    
    hDatatip = createDatatip(cursorMode, hObj);
    
    % adjust properties
    set(hDatatip, 'UIContextMenu', get(cursorMode, 'UIContextMenu'));
    set(hDatatip, 'HandleVisibility', 'off');
    set(hDatatip, 'Host', hObj);
    set(cursorMode, 'DisplayStyle', 'window');
    
    % set up listener to datatip
    h = handle.listener(hDatatip, 'UpdateCursor', {@localUpdatePanel,hTool});
    addlistener(hDatatip,h);

    % Listen to datatip existence and feed to panel
    h = handle.listener(hDatatip, 'ObjectBeingDestroyed', {@localUpdatePanel,hTool});
    addlistener(hDatatip,h);
    
    localPanelUIOn(hMode,hTool);
    set(get(hDatatip,'TextBoxHandle'), 'Visible', 'off');

    % Update string in panel
    localUpdatePanel([],[],hTool);
    
    % create datatip
    xData = get(hObj, 'XData');
    yData = get(hObj, 'YData');
    pos = [xData(index) yData(index)];
    set(get(hDatatip, 'DataCursor'), 'DataIndex', index, 'TargetPoint', pos);
    set(hDatatip, 'Position', pos);
    updateDataCursors(cursorMode);
end

#24 Comment By Werner On July 17, 2013 @ 08:42

I’ve used your datatip “undocumented documentation” and it helped me a lot with enhancing the information extraction from graphics. However, the datatips have an unexpected behavior on mac users, which makes it bottom of the ylabel text, complicating their visualization. I’ve managed to solve this issue explicitly overriding the position of the ylabel to a z value lower than the datatip one, but now my ylabel will move around when I zoom or pan my axis. I over-read the ActionPostCallback function from the zoom and pan handles, to replace the position after there where a change on the axis, but this creates an effect like the one you explained here:

[21]

By chance, do you know any event listener that is linked to the axis label, or to movement on the axis, so that I can solve this issue without seeing my axis label flying around my figure until mouse is released? More details available here:

[22]

Thank you very much, and congratulations for this site, it is very useful!

#25 Comment By Yair Altman On July 17, 2013 @ 17:00

@Werner – you can set a [23] on the axis’s XLim / YLim properties. Note that this specific functionality requires a different syntax in the [24] compared to the current HG1.

#26 Comment By Julien On July 18, 2013 @ 12:56

Yair,
I massively abuse of the handle.listener syntax to listen to property changes of UDD objects. Could you give an example of what the equivalent syntax looks like in HG2 ?
Moreover, do you know if the same handle.listener syntax still works in HG2 to listen to java events ?
Thanks !

#27 Pingback By Draggable plot data-tips | Undocumented Matlab On October 23, 2013 @ 15:01

[…] object exposed via the datacursormode function. I have already shown how these can be used to customize and control data-tips programmatically (rather than interactively). For draggableDataTips, we first get the cursor object’s […]

#28 Comment By Franko On November 7, 2013 @ 19:37

The graphics.datacursormode object has an UpdateFcn handle. Opening graphics.datatip.updatestring.m reveals that the graphics.datatip object itself has an UpdateFcn. The latter is more useful because the cursorMode UpdateFcn is called as

myUpdateFcn([], hDatatipEvent);

whereas the datatip object’s UpdateFcn is called as

myUpdateFcn(hDatatip, hDatatipEvent);

So, potentially you can have different datatips with different UpdateFcn in the same figure. This is useful for advanced visualization involving multiple datatips in the same figure.

#29 Comment By Graham On January 9, 2014 @ 13:43

Great article Yair, a nice insight into the workings of data tips. Is there any way you know in which HTML can be included in data tips?
I’m running R2011b & interested in being able to provide links with matlab: href to trigger some activity.

I’ve tried the simple way of just outputting HTML from the UpdateFcn (as below) but without any success

txt = sprintf(' [25]');

#30 Comment By Yair Altman On January 9, 2014 @ 14:45

@Graham – data-tips are simply axes text objects, so they can be formatted with Tex/Latex but not HTML.

#31 Comment By Jon On March 27, 2014 @ 13:35

Hi Yair,

I used this excellent writeup to create custom tooltips for a bunch of figures. Everything mostly works, but the above method fails in one case, and I have no idea why.

Briefly: I create a single empty figure and set its WindowButtonDownFcn property to @myMagnifyFcn. I then plot nine subplots (arranged as 3×3) into that figure. The helper script myMagnifyFcn determines which of the subplots receives a mouse click, then creates a new figure and copies just that axes into it (using findobj, etc.). This much works just fine.

I then attempt to create the “custom tooltip” functionality for the latter (one-axes) figure as per your example, namely:

cursormodeMagnifiedFig = datacursormode(gcf);
set (cursormodeMagnifiedFig, 'NewDataCursorOnClick', true, 'SnapToDataVertex', on, 'UpdateFcn' {@myToolTipFcn, arg1, arg2, arg3});

This is exactly the same code that I have working for other figures. But in this case, even though I can toggle the data cursor button in the latter figure just fine, @myToolTipFcn never seems to get called — I put a debug print statement at the top and it never executes.

I’m wondering if there is something scope-related that causes the above to fail. As I said, the datacursormode stuff works just fine for all the other figures I create in my parent script. Furthermore, I examined the contents of cursormodeMagnifiedFig in the debugger — it turns up as a graphics.datacursormanager object, just like the corresponding cursormodeFig does with all my “regular” figures, and the contents are identical in all cases — so I’m confident that the arguments to UpdateFcn (= myToolTipFcn) are getting passed correctly.

I’m stuck because I can’t figure out (no pun intended) how to debug what Matlab is doing — it simply doesn’t fire the helper function and fails silently. Can you suggest any good way to debug the datacursormode process?

Thanks very much in advance (for this post specifically and for the blog in general),

Jon

#32 Comment By Yair Altman On March 27, 2014 @ 13:54

@Jon – your gcf probably points to another figure handle. Try using the actual figure handle rather than gcf – if it’s a hidden handle then gcf will not return it.

#33 Comment By Jon On March 27, 2014 @ 14:24

Hi Yair,

Thanks for the quick response. I had a hunch that might be an issue, but wrote “gcf” in my code snippet above for brevity. Since that apparently _does_ make a difference, I should clarify that the actual setup in myMagnifyFcn is

h_magnifiedFig = figure('tag', 'magnifiedAxes', 'keyPressFcn', get(hobj, 'keyPressFcn'), 'Name', 'Magnified Axes');
cursormodeMagnifiedFig = datacursormode(h_magnifiedFig);
set (cursormodeMagnifiedFig, 'NewDataCursorOnClick', ...);

… and it is this setup that doesn’t work. I’m really baffled as to how else to debug this.

FWIW, I’m stuck using a R2006b on this project. Seems much more likely that it’s my fault and not Matlab’s, but any chance this could be an HG-related bug?

Jon

p.s. Sorry about the double post earlier, and thanks for cleaning it up.

#34 Comment By Yair Altman On March 27, 2014 @ 14:28

Try adding a drawnow; pause(0.1); after the figure creation and before you retrieve datacursormode, maybe it will help. I no longer have access to R2006b (too old) so I can’t test. Good luck!

#35 Comment By Jon On March 27, 2014 @ 14:41

Tried that but no luck. Argh.

FWIW, checked that gcf, h_magnifiedFig, and get(gca,’Parent’) [where gca is the axes copied into the magnified figure] are all equal to one another — so the issue isn’t with operating on the wrong (or hidden) figure handle.

Anyway, I will try digging a bit further with the debugger and maybe ask over at the newsgroup to see if anyone else has an idea. In any case, I will report back if I ever get to the bottom of this.

Thanks again,

-Jon

#36 Comment By Jon On March 27, 2014 @ 19:02

I think I’ve found a solution. Following up here as promised, in the unlikely event someone else runs into this (obscure?) issue.

In my @myMagnifyFcn callback, the relevant part of the code to copy the clicked-upon axes and its contents to the new empty figure window is as follows:

% Find all axes that are just axes (as opposed to legends, colorbars, etc.)
figAxes = findobj(hObject, 'type', 'axes', '-not', 'tag', 'legend', '-not', 'tag', 'Colorbar');
indAxes = find(figAxes == gco);

% Assuming the click uniquely selects a particular axes, copy it to a new figure along with its contents
if length(indAxes) == 1,
    h_magnifiedFig = figure('tag', 'magnifiedAxes', 'keyPressFcn', get(hobj, 'keyPressFcn'), 'Name', 'Magnified Axes');
    zoomedAxes = copyobj(figAxes(indAxes), h_magnifiedFig);
end;

(Note that legends and colorbars are handled separately later in the function, since I’ve found that COPYOBJ does not seem to handle them correctly, at least on R2006b.)

The problem is that COPYOBJ either also mis-copies the ‘hittest’ property of some (all?) objects, or else they are not inherited automatically from the parent figure. This causes subsequent mouse clicks into the new (“magnified”) figure to be ignored, so they fail to fire the callback.

So, after all that, the solution to this problem seems to be a one-liner(!) following the COPYOBJ statement:

set(findobj(gcf,'type','patch'),'hittest','on')

and some small tweaks to the code that assembles the tooltip text (which are specific to my setup, so I’ll skip them here).

Hope this helps someone in the future. Thanks again, Yair, for doing all the heavy lifting.

-Jon

#37 Comment By Jon On March 31, 2014 @ 16:29

One more…

I have a callback function outputTxt = myCallback(obj, eventObj) to create customized datatips as described here, but I need to limit that behavior to only work for certain objects (specifically, plotted data points only, and not other lines showing mean, standard deviation, etc.).

I’m able to check which object is clicked selected with the data cursor by looking at the properties of clickedObj = get(eventObj, ‘target’). But even if I set outputTxt = {”}, I still get a (default) data tip. I would like to cleanly delete this.

The “Deleting data tips” section above shows how to do this from the parent script, but I’m wondering if it is possible to do this _from within the callback_. The variable obj is empty, while eventObj (whose class is graphics.datatipevent) has two properties, Target (a handle) and Position (a 2×1 matrix) — neither of which points to the datacursormode object used in the example. As a last resort, I tried executing this inside the callback:

dummy = datacursormode(gcf);
dummy.removeDataCursor(dummy.CurrentDataCursor);

… and that sort of works, except that sometimes it deletes not only the desired (errant) data tip but also other (valid) ones already created in the same figure, which should all be left alone.

Any suggestions would be most welcome.

Thanks,

-Jon

#38 Comment By Mahmoud On June 26, 2014 @ 05:53

Thanks Dr.Yair Altman for your really nice tutorial.
I am writing a program with 4-context menus; one of them is related to datacursor mode, I can switch between any of them except datacursormode one, I CANNOT Switch it off, So pleae how to do it in some example demo?
Thanks in advance

#39 Comment By Yair Altman On June 27, 2014 @ 00:38

@Mahmoud – I am not sure I understand your problem exactly. If you’d like me to look at your code, please contact me via email (the link is at the top left of every page here) for a short consultancy.

#40 Comment By Mahmoud On June 27, 2014 @ 16:42

function CursorMode_Off_test
   close all, clear all, clc;
   f=figure;
   xdata=-10*pi:pi/10:10*pi;ydata=sin(xdata);
   hLine = plot(xdata, ydata);
   %%================================================================================
   hax=gca;
   hcmenu = uicontextmenu;
   h1=uimenu(hcmenu,'label','Line Style');
   h2=uimenu(hcmenu,'label','Color');
   %
   hcb1 = ['set(gco,''LineStyle'',''--'')'];
   hcb2 = ['set(gco,''LineStyle'','':'')'];
   hcb3 = ['set(gco,''LineStyle'',''-'')'];
   hcb_r = ['set(gco,''color'',''r'')'];
   hcb_g = ['set(gco,''color'',''g'')'];
   hcb_b = ['set(gco,''color'',''b'')'];
   hcb_B = ['set(gco,''color'',''k'')'];
   %
   item1 = uimenu(h1,'Label','dashed','Callback',hcb1);
   item2 = uimenu(h1,'Label','dotted','Callback',hcb2);
   item3 = uimenu(h1,'Label','solid','Callback',hcb3);
   item4 = uimenu(h2,'Label','red','Callback',hcb_r);
   item5 = uimenu(h2,'Label','green','Callback',hcb_g);
   item6 = uimenu(h2,'Label','blue','Callback',hcb_b);
   item7 = uimenu(h2,'Label','black','Callback',hcb_B);
   %How to turn on/off this menu and keep other menus work
   item8 = uimenu(hcmenu,'Label','Cursor Mode','Callback',@update_FCN_call);
   %
   hlines = findall(hax,'Type','line');

   for line = 1:length(hlines)
      set(hlines(line),'uicontextmenu',hcmenu)
   end
end

function update_FCN_call(~,~)
    cursormode = datacursormode(gcf);
    set(cursormode,'enable','on','UpdateFcn', @myupdatefcn);
end

function cp = myupdatefcn(obj,event_obj)
    pos = get(event_obj,'Position');
    cp = {['X: ',num2str(pos(1))], ...
          ['Y: ',num2str(pos(2))]};
end

#41 Comment By Rick On July 22, 2014 @ 14:18

I create a plot and set the data cursor properties in a function using:

dcm_obj = datacursormode(gcf);
set(dcm_obj,'DisplayStyle','datatip', ...
  'SnapToDataVertex','on', 'Enable','on', ...
  'UpdateFcn',@FreqRespDataCursor);

I then attempt to change the font to ‘FixedWidth’ (so my formatted strings all line up) by using:

set(dcm_obj.CurrentDataCursor,'FontName','FixedWidth');

However, when I use the data cursor, everything is as it should be except the font is still the default ‘Helvetica’. If I call this code from the command line it works fine. Any ideas what is wrong?

#42 Comment By Yair Altman On July 25, 2014 @ 11:49

@Rick – this is possibly an internal Matlab bug. Try using an explicit font name (e.g. ‘Courier New’) or use HTML formatting in your string (e.g., ‘my data tip string here…’)

#43 Comment By Yaroslav On August 10, 2014 @ 23:20

I have noticed that some properties change their enumeration values between HG1 and HG2. For example the 'Orientation' field changes from 'top-right' to a simple 'topright' etc. Perhaps it is worth mentioning it both in the current article and in [26].

On another notice, in some cases using HG2 the data-tips are created (and changed programmatically) faster. They have also a much richer data-tip display (using TeX syntax and notation). It seems that MathWorks makes some really good job under the hood…

#44 Comment By xiaojidan On January 27, 2015 @ 04:42

Do you know how to add two different markers on two ends of a line?

#45 Comment By Yair Altman On January 27, 2015 @ 04:49

@xiaojidan – you can simply use separate plot() commands, each one for a different marker.

#46 Comment By bash0r On February 18, 2015 @ 08:09

I’m plotting an image in MATLAB using imagesc and then selecting points with the datacursormode.
I’d like to any select point on the image not only the pixels itself.
That’s why I always used ‘SnapToDataVertex’, ‘off’ in MATLAB R2014a.

After switching to MATLAB R2014b. The cursor nethertheless snaps to the data vertex.

dcm_obj = datacursormode(h);
set(dcm_obj, 'DisplayStyle', 'datatip', 'SnapToDataVertex', 'off', 'Enable', 'on');

I can only select pixel (e.g. X=75 Y=122) but I have to be able to select points in the sub-pixel region (e.g. X=75.25 Y=122.78).
Has something changed in R2014b? How can I achieve the old behavior?

Thanks in advance!

#47 Comment By Yair Altman On February 20, 2015 @ 01:37

@bash0r – this looks like a Matlab bug to me. I suggest that you contact [27] to report it

#48 Comment By bash0r On February 21, 2015 @ 06:37

I have contacted the MATLAB support:

“In R2014b, MATLAB has a new graphic handle system, so the image is visualized in a different way, which affect the behavior of setting ‘SnapToDataVertex’ ‘off’. If you are plotting lines, you can still have the same behavior.”

The support is looking for a workaround to achieve my task and has additionally contacted the development team.

I’ll keep you guys posted.

#49 Comment By bash0r On February 23, 2015 @ 08:43

I’ve received an answer from the MATLAB support and they have sent a workaround for MATLAB R2014b to get the exact cursor location on an image.
Maybe someone is also in desperate need of this functionality 🙂

load clown % load any image data (here: stored in variable X)
h = figure(1);
clf
s = surf(zeros(size(X)+1), X, 'FaceColor', 'flat', 'EdgeColor', 'none'); % plot the image points as a surface
set(gca, 'YDir', 'reverse')
view(gca, 2)
axis(gca, 'tight') 

dcm_obj = datacursormode(h); 
set(dcm_obj, 'DisplayStyle', 'datatip', 'SnapToDataVertex', 'off', 'Enable', 'on');

#50 Comment By skratch On April 24, 2015 @ 10:15

I just updated to R2014b and I’m having problems with code that just worked yesterday before the update. I used the top portion of code on this page to make a function createDataCursor(figureHandle,plotHandle,xcoord,ycoord). After the update, ‘NewDataCursorOnClick’, ‘ViewStyle’, and update pop up with errors that they don’t work for data tips:

The name 'NewDataCursorOnClick' is not an accessible property for an instance of class
'matlab.graphics.shape.internal.DataCursorManager'.  
There is no ViewStyle property on the PointDataTip class.
Undefined function 'update' for input arguments of type 'matlab.graphics.shape.internal.PointDataTip'.

The Matlab documentation says, “You place data tips only by clicking data objects on graphs. You cannot place them programmatically (by executing code to position a data cursor).” I don’t know if it always said that or if that’s updated language as of R2014a/b. The first two errors are not a big deal, but I don’t know what to do about “update” no longer working. How do I update the position of the data tip to a new location?
Sample of my function below:

function output_args = createDataCursor(figureHandle,plotHandle,xcoord,ycoord)
   cursorMode = datacursormode(figureHandle);
   set(cursorMode, 'enable','on', 'UpdateFcn',@setDataTipTxt)
   hTarget=handle(plotHandle);
   hDatatip=cursorMode.createDatatip(hTarget);
   set(hDatatip, 'UIContextMenu', get(cursorMode,'UIContextMenu'));
   set(hDatatip, 'HandleVisibility','off');
   set(hDatatip, 'Host',hTarget);

   % set(hDatatip, 'ViewStyle','datatip');
   set(hDatatip, 'MarkerSize',5, 'MarkerFaceColor','none', 'MarkerEdgeColor','k', 'Marker','o', 'HitTest','off');
   position=[xcoord,ycoord];
   update(hDatatip,position);
end

#51 Comment By Yair Altman On April 25, 2015 @ 10:39

If you read the article you’d see that the Matlab warning has always been there. R2014b introduced a major overhaul of the entire graphics system (a.k.a. [26]), and this functionality has changed with it. It can still be accessed programmatically, it’s just that the programmatic interface has changed. This is always a risk when using undocumented features such as the ones explained in this blog. You cannot expect them to remain unchanged forever…

You’d need to dig a bit to find out the required changes in 14b – I’m too busy working on other things now and do not expect to look into this in the near future. If you find anything useful, come back here and post it for the benefit of other readers.

Good luck!

#52 Comment By Will On May 27, 2015 @ 13:13

In HG2, the data tip object has Cursor property, which itself has a Position property. Setting this property to a new location updates the position of the data tip, i.e.:

hDatatip.Cursor.Position = [xcoord, ycoord];

#53 Comment By Will On May 28, 2015 @ 01:25

Note that unlike with the previous update() method, setting the value of hDatatip.Cursor.Position only triggers the UpdateFcn() callback if the value is not equal to the current position.

#54 Comment By John P On March 10, 2016 @ 09:42

Hello,
I’m trying to copy an existing figure to a newly created figure.
say.. i’ve just created a figure with a few subplots and added a bunch of datacursors. call it “old_fig”.

%old_fig = a bunch of subplots etc...
new_fig = figure;
copyobj(allchild(old_fig),new_fig);

this copies everything except for the datacursors.

Does anyone know how to copy the datacursors over also?

Cheers!!

#55 Comment By MU On March 20, 2016 @ 16:45

Hi Yair

Many thanks for the excellent article.

I was wondering if in the datacursor mode, instead of showing the standard datatip, there is an efficient way to draw a vertical line that passes through the graph and intersects the y-value at/above/below the click position.

Many thanks,
MU

#56 Comment By Yair Altman On March 20, 2016 @ 17:17

@MU – of course this is possible, but you would need to do this programmatically, by trapping the mouse-movement events in a callback. See an example here: [28]

#57 Comment By Jason On April 9, 2016 @ 23:57

I changed the font in my data tip to Courier New. This works great when the data tip display style is ‘Data Tip’…..but the appearance of the font reverts to Helvetica when the display style is ‘window’ even though cursorMode.DisplayStyle still shows Courier New.

Any thoughts on why the appearance would change between the two display styles?

I change the font from within the data tip function:

function output_txt = track_assess_ppi_data_tip(obj,event_obj)
    ...
    cursorMode = datacursormode(gcf);
    cursorMode.CurrentDataCursor.FontName ='Courier New';
    ...
end

#58 Comment By Jason On April 10, 2016 @ 01:06

Never mind……figured it out.

When you switch from the ‘Data Tip’ display style to the ‘window’ display style, the original data tip object still remains but ‘visible’ is turned ‘off’.

Then a panel is created to hold the same content that is in the data tip.
I was able to find the handle for that panel and set its font to ‘Courier New.’
Code is below:

function output_txt = track_assess_ppi_data_tip(obj,event_obj)
   ...
   cursorMode = datacursormode(gcf);
   cursorMode.DisplayStyle = 'window';
   cursorMode.CurrentDataCursor.FontName ='Courier New';  % this does the data tip
   my_figpanel = findall(gcf,'Tag','figpanel:text field');
   set(my_figpanel,'FontName','Courier New')
   ...
end

#59 Comment By Nick Gianopoulos On September 16, 2016 @ 02:27

Yair,

I’m sorry if this is a repeat question as I feel somebody probably has asked it before, but I’ve scoured this thread and still haven’t found the answer to my question. I’m using trisurf(tri,x,y,z,c) to plot a 3D color plot. The datatip function by default displays X Y Z using the Position property of of the event_obj. However, I looked through your list of the hidden properties of the event_obj but couldn’t find one that referred to the argument passed to the color input. I’d like to be able to edit the datatip function to show X,Y,Z,and Heat (which is what the color represents in my case).

Thanks,

Nick

#60 Comment By Yair Altman On September 16, 2016 @ 09:51

@Nick – all you need to do is to set a custom UpdateFcn callback function for the cursorMode object (in my post it was @setDataTipTxt). This callback function should have the simple following signature:

function outputTxt = setDataTipTxt(hObject, eventObj)

within this callback function, eventObj.Target will be the handle of the surface object, and eventObj.Position will be the data-tip’s X,Y,Z data coordinates. Use these coordinates (which correspond to a single point in the surface object’s XData,YData,ZData properties) to extract the corresponding C value from the surface object’s CData property (which has the same matrix size as ZData, thus enabling easy match). Then combine X,Y,Z,C into a string that you will set in outputTxt. That’s it. See the [18] for details.

#61 Comment By Nick Gianopoulos On September 16, 2016 @ 20:50

@Yair, Worked beautifully – Thanks!

#62 Comment By Hans On October 19, 2016 @ 13:21

Hi,

I need to write the x axis difference between two or 4 datatips on the plot like legend.
Text function writes everytime as I zoom in.

Questions :

1) if marker one is the reference and if there is 4 markers, I need to calculate 3 distance w.r.t. marker one.
2) How to plot these mentioned 3 distances on the plot( by zooming into plot it will stay as legend )

I appreciated too much for your help.

WR
Hans

#63 Comment By Andrew On December 8, 2016 @ 18:55

Hello,

Did MATLAB recently change the syntax to this? I am trying to get access to the current list of datacursors programatically, but nothing I have tried seems to work.

>> cursorMode = datacursormode(handles.figure1)

cursorMode = 

  DataCursorManager with properties:

        SnapToDataVertex: 'on'
            DisplayStyle: 'datatip'
    DefaultExportVarName: 'cursor_info'
               UpdateFcn: @dynamicDateTicks/dateTip
                  Enable: 'off'
                  Figure: [1x1 Figure]

So not nearly as many properties are listed as above. Then, the next call to get the current data cursors does not work anymore

>> dcm.DataCursors
No appropriate method, property, or field 'DataCursors' for class
'matlab.graphics.shape.internal.DataCursorManager'.

I am trying to make a GUI which gets the xy data from all plotted datacursors. I have not figured out how to do this programmatically unless I am creating the datatips programmatically and then storing them in my own cells. Currently, I have to have the user “export cursor data to workspace” by right clicking the datatip and doing it manually. This is rather clunky.

Any suggestions are appreciated – thanks!

#64 Comment By Andrew On December 8, 2016 @ 19:05

I figured it out…actually found it elsewhere but then realized it is mentioned in this original post as well. You can still use getcursorinfo(dcmObject) to get a list of all data cursors.

#65 Comment By Yair Altman On December 8, 2016 @ 19:13

yes, this post was originally posted in 2011, more than 5 years ago – Matlab has changed a lot since then, including an entirely revised graphics system (HG2). The current data cursor object is similar, but not identical, to the one mentioned in the post. So if you just figure out how the property names have changed you could probably do everything now much as you could back in 2011. For example, the current data-cursor object can be gotten via cursorMode.CurrentCursor instead of using CurrentDataCursor.

#66 Comment By Michael On February 17, 2017 @ 17:10

Dear Yair
I would like to make some of the lines on the plot “unaccessible” / “invisible” for the datacursor mode
(Thus, I want the possibility to place the data cursor only on part of the lines that appear on the plot).
How can I do that, please?
Thank You
Michael

#67 Comment By Yair Altman On February 18, 2017 @ 21:16

@Michael –

set(hLines,'HitTest','off')

#68 Comment By Sanwal Yousaf On March 18, 2017 @ 01:56

Hey Dr. Altman,
This is a great tutorial though i am trying to adjust it to my script. I have a figure with 13 subplots in it that each have boxplot representation of the data that i am working with. I am trying to modify the data tip text for the outliers so that i can use the Observation row value that is displayed in the data tip. I want to introduce another value in the datatip that takes the value of Observation Row as displayed in the data tip and use it to display the subject number that is stored in a separate matrix that is generated before the boxplots are plotted. I am using Matlab R2013a and i am trying to adjust your code to my script and i am getting an error that reads:

No appropriate method, property, or field CreateDatatip for class graphics.datacursormanager.

for the following line of code:

hDatatip = cursorMode.CreateDatatip(hTarget);

I am still in work of adjusting this to my script, here are some adjustments that i have made so far:

cursorMode = datacursormode(gcf);
set(cursorMode, 'enable', 'on', 'UpdateFcn', @revealData);

hTarget= handle(gcf);
hDatatip = cursorMode.CreateDatatip(hTarget);

%Create a copy of teh context menu for the data tip
set(hDatatip,'UIContextMenu',get(cursorMode,'UIContextMenu'));
set(hDatatip,'HandleVisibility','off');
set(hDatatip,'Host',hTarget);
set(hDatatip,'ViewStyle','datatip');

%set the data-tip orientation to top-right rather than auto
set(hDatatip, 'OrientationMode', 'manual');
set(hDatatip, 'Orientation', 'top-right');

%update the data tip marker appearence
set(hDataip, 'MarkerSize', 5, 'MarkerFaceColor', 'none',...
             'MarkerEdgeColor', 'k', 'Marker', 'o', 'HitTest', 'off');

%Move the data tip to the right most data vertex point
position = [X(end),dataExtract(end),1; X(end),dataExtract(end),-1];
update(hDatatip, position);

Here is my update function

function txt = revealData(~, event_obj)
    %Customizes the text of data tips
    pos = get(event_obj, 'Position');
    pos1 = pos(1);
    pos2 = pos(2);
    txt = {['Outlier Value', num2str(pos(1))],...
           ['SubName', mat(pos2).name]};
end

I am also linking my Matlab Answers post which has an image of the subplots that i am refering to.

I would greatly appreciate any help i can get.
[29]

P.S. Sorry if the indenting looks poor, i already made sure that indenting wasn’t the problem!!

#69 Comment By gep On March 6, 2019 @ 23:41

Hi,

Is it possible to maintain the hittest property of a figure after enabling datacursormode?

f = figure('WindowButtonUpFcn',@(~,~)disp('UP!!'));
z = peaks;
plot(z(:,30:35));
%
dcm_obj = datacursormode(f);
set(dcm_obj,'DisplayStyle','datatip',...
    'SnapToDataVertex','off','Enable','on')

Thank you

#70 Comment By gep On March 7, 2019 @ 19:37

To answer myself in case someone stumbles upon:

add this snippet inside your datacursor update function,

hManager = uigetmodemanager(h_fig);
try
    set(hManager.WindowListenerHandles, 'Enable', 'off');  % HG1
catch
    [hManager.WindowListenerHandles.Enabled] = deal(false);  % HG2
end

followed by setting any figure callbacks you want to survive while datacursor mode is enabled

@Yair, I am almost certain that I have read it in one of your answers somewhere but I have forgotten about it.
Hard to keep track of all the hacks:)

#71 Comment By Yair Altman On March 7, 2019 @ 19:56

@Gep – I believe that you found it here: [30] (October 2015)

#72 Comment By gep On March 7, 2019 @ 20:28

ah yes.. i have stolen this hack years ago:)

#73 Comment By Mike Papadopoulos On May 8, 2019 @ 21:01

Using MATLAB 2018b, I have been able to change the EdgeColor and TextColor of the datatip, but the BackgroundColor will not update properly. Specifically the BackgroundColor property of the datatip object changes to the correct RGB triplet but the actual Background color of the datatip does not change. Any Thoughts?

#74 Comment By Yair Altman On May 21, 2019 @ 13:07

@Mike – you can modify the tip background via the TipHandle and/or BackgroundAlpha:

hDataTip.TipHandle.FaceColor = 'm';  % or: [1,0,1]
hDataTip.BackgroundAlpha = 0.65;

#75 Comment By Jacopo Remondina On July 22, 2019 @ 17:41

Hi, I’m working with MATLAB R2019a – update 4 (the latest one I think), and I would like to know if there are some updates on how these features work.
Actually some of the functionalities are still correct/working, like querying for the datacursormode (or manager) and set the update string function, but other (like querying for all the datacursor objects) seems broken. I also noticed that maybe the object itself is a bit different. Here are the outputs I’ve got at the prompt:

>> dcm=datacursormode(figHandle)
dcm = 
  DataCursorManager with properties:
        SnapToDataVertex: 'on'
            DisplayStyle: 'datatip'
    DefaultExportVarName: 'cursor_info'
             Interpreter: 'tex'
               UpdateFcn: @(varargin)obj.manageDatatips(varargin{:})
                  Enable: 'on'
                  Figure: [1×1 Figure]

>> dcm.DataCursors
Unrecognized method, property, or field 'DataCursors' for class 'matlab.graphics.shape.internal.DataCursorManager'.

In particular, I would like to know if there is a way to change the default aspect of the markers for a given figure, since the workaround I’ve found is to change each property (marker shape, size, edge color, face color,…), then force an update (with pause), then change another property and so on.
This method has however few drawbacks:
-first, the middle step settings flash on the screen (and without the pause command between them, they are not accepted);
-second the changes are only temporary and I should update them every time the markers are drawn again, including during the resize of the figure/axes

I tried to have a look with the getundoc function, but I couldn’t really find anything useful.
Thanks,
Jacopo

#76 Comment By Yair Altman On July 27, 2019 @ 23:53

@Jacopo – in R2019a the property is called PointDataCursors. Since it’s a private property of the datacursoremode, you cannot access it directly. Instead, use struct(dcm).PointDataCursors. I am not aware of a way to change the data-cursor defaults – perhaps there is a way, I just never bothered to look for one.

#77 Comment By CW On August 5, 2019 @ 19:26

Hi. I have a contour plot with multiple data sets plotted on it, i.e…

[cs1,h1] = contour(x1,y1,z1);
hold on;
[cs2,h2] = contour(x2,y2,z2);
[cs3,h3] = contour(x3,y3,z3);

Generally with data cursor, I’d have to click around in the plot to get the data cursor to show each of the z1, z2, z3 data separately, along with its legend entry, hoping I click on the exact contour I want.

I would like to see if there’s a way to use myupdatefnc to show all 3 z data values at a particular x,y position in a single data cursor. Do you know if this is possible? Thank you!

#78 Comment By CW On August 5, 2019 @ 21:12

Also to clarify, this is within a GUI, which allows users the ability to choose which of a set of, say, 10 types of data they want, as many as they want, to be plotted. So an automatic way of doing this, rather than passing in 3 specific data sets and pulling them out manually based on the current x,y would be helpful.

#79 Comment By Yair Altman On August 6, 2019 @ 11:50

@Aselia/CW – In your updateFcn(~,eventData) function, you can fetch the clicked position via eventData.Position and based on this position you can compose your custom datatip text (which is returned as the output of updateFcn). Simply find a way to get the contours data accessible in your updateFcn (there are multiple ways to do this, all of them pretty standard/documented) and you’re basically done.

#80 Comment By CW On August 28, 2019 @ 21:04

I was able to get the contour data accessible within myupdatefnc, however I noticed that eventData.Position returns the absolute x,y position, whereas my contour z data might have a certain step size between data points such that the absolute x,y position doesn’t access the array correctly. Is there a way to do this without also pulling in my original x,y vectors, step size, etc and doing all the math myself? Doing the math and pulling the data in is fine…just wanted to avoid the extra bulk if possible.

#81 Comment By Leandro de Oliveira On October 2, 2019 @ 01:17

My contribuition to create new datatip

clc
clear all
close all

x = 0:0.1:10;
y = sin(x);

h = figure(1);
hObj = plot(x,y);
index = [25 75 100];
hold on
for i = 1:3
    cursorMode = datacursormode(h);
    hDatatip = cursorMode.createDatatip(hObj);
    pos = [x(index(i)) y(index(i))];
    set(get(hDatatip,'DataCursor'), 'DataIndex',index(i), 'TargetPoint',pos);
    set(hDatatip, 'Position', pos);
    updateDataCursors(cursorMode);
end
hold off

#82 Comment By Ajay Krishna On June 8, 2020 @ 09:41

Is it possible to add custom data tip for simulink blocks without using the description or Block Name or parameter names and values.To make my statement clear i want to add custom data tip without altering the blocks


Article printed from Undocumented Matlab: https://undocumentedmatlab.com

URL to article: https://undocumentedmatlab.com/articles/controlling-plot-data-tips

URLs in this post:

[1] data tips: http://www.mathworks.com/help/matlab/creating_plots/data-cursor-displaying-data-values-interactively.html

[2] datacursormode: http://www.mathworks.com/help/techdoc/ref/datacursormode.html

[3] data-brushing: http://undocumentedmatlab.com/blog/accessing-plot-brushed-data/

[4] MakeDataTip: http://www.mathworks.com/matlabcentral/fileexchange/19877-makedatatip

[5] uiinspect utility: http://www.mathworks.com/matlabcentral/fileexchange/17935-uiinspect-display-methods-properties-callbacks-of-an-object

[6] comment: http://undocumentedmatlab.com/blog/controlling-plot-data-tips/#respond

[7] Draggable plot data-tips : https://undocumentedmatlab.com/articles/draggable-plot-data-tips

[8] Accessing plot brushed data : https://undocumentedmatlab.com/articles/accessing-plot-brushed-data

[9] Plot LimInclude properties : https://undocumentedmatlab.com/articles/plot-liminclude-properties

[10] Undocumented plot marker types : https://undocumentedmatlab.com/articles/undocumented-plot-marker-types

[11] Plot markers transparency and color gradient : https://undocumentedmatlab.com/articles/plot-markers-transparency-and-color-gradient

[12] Plot line transparency and color gradient : https://undocumentedmatlab.com/articles/plot-line-transparency-and-color-gradient

[13] : http://k43.kn3.net/taringa/1/1/2/2/8/1/99/bigmaster2012/CF8.jpg?469

[14] : http://www.mathworks.com/help/techdoc/ref/datacursormode.html#zmw57dd0e87879

[15] : https://undocumentedmatlab.com/blog/undocumented-cursorbar-object/

[16] : http://blogs.mathworks.com/videos/2011/10/19/tutorial-how-to-make-a-custom-data-tip-in-matlab/

[17] : http://www.mathworks.com/help/techdoc/creating_guis/f16-999606.html#brqoxlk

[18] : http://www.mathworks.com/help/matlab/ref/datacursormode.html

[19] : http://blogs.mathworks.com/videos/2012/09/19/making-a-custom-data-tip/

[20] : http://blogs.mathworks.com/videos/2011/02/25/creating-a-custom-data-cursor/

[21] : https://undocumentedmatlab.com/blog/setting-axes-tick-labels-format/

[22] : http://stackoverflow.com/questions/17584094/put-datatip-stack-on-top-of-axis-label-and-update-axes-label-after-a-change-was

[23] : https://undocumentedmatlab.com/blog/continuous-slider-callback/#Property_Listener

[24] : https://undocumentedmatlab.com/blog/hg2-update/

[25] : http://undocumentedmatlab.comwhy

[26] : https://undocumentedmatlab.com/blog/hg2-update

[27] : mailto:support@mathworks.com

[28] : https://undocumentedmatlab.com/blog/transparent-legend

[29] : https://www.mathworks.com/matlabcentral/answers/330463-custom-data-tips-for-boxplots

[30] : https://undocumentedmatlab.com/blog/enabling-user-callbacks-during-zoom-pan

Copyright © Yair Altman - Undocumented Matlab. All rights reserved.