MATLAB: How to get pixel’s position of an image in UIAxis in AppDesigner

appappdesignercursordatacursordatacursormodedatatipimageMATLABuiaxesuiaxisuifigure

I have to show a very large image(the size is about [230,1e4~1e5]) with AppDesigner. And I want to get any pixel's X/Y position for later code. After some times' test, it could be displayed successfully with image(app.modelObj.Image,'Parent',app.PictureUIAxes); But I found the UIAxis controller can't support the datatip or datacursor tool any more…
So I try to set a customized call_back for the UIAxis to get the pixel's position when I click on it, or try to set a call_back attribute just like 'ButtonDownFcn' to active someting. But I don't know how to write the code. What should I do then?

Best Answer

Description of the problem
The data cursor does not work for image objects plotted in App Designer (or in any uifigure) in r2020a. AppDesigner features are still being rolled out with every release of Matlab. For example, data tips have been implemented in r2020a. But for image objects, the datacursor still does not work.
Here is a demo of the problem using a legacy figure and a uifigure.
% Create image data
imageData = randi(100,10,12);
% Show image in legacy figure and turn on datacursor
fig = figure();
ax = axes(fig);
image(ax,imageData);
ax.Colormap = jet(100);
dcm = datacursormode(fig);
dcm.Enable = 'on';
title(ax, 'Legacy figure')
% Show the same image in uifigure and turn on datacursor
uifig = uifigure();
uiax = uiaxes(uifig, 'Position', [10 10 500 410]);
image(uiax,imageData);
uiax.Colormap = jet(100);
axis(uiax,'tight')
dcm = datacursormode(uifig);
dcm.Enable = 'on';
title(uiax,'uifigure')
As you can see, the datacursor appears as exected in the legacy figure but in the uifigure, a message appears, Unrecognized method. property, or field 'ColorSpace' for class 'matlab.ui.control.UIAxes'
Solution
Until Matlab suports datacursors with images in UIAxes, you can create a custom update function for the datacursor object within the UIAxes/UIFigure. This demo shows how to recreate the datacursor text produced in the legacy figure.
Continuing from the example above,
% Step 1: Turn on datacursor mode in the UIFigure
% uifig is the figure handle to the uifigure or the app
dcm = datacursormode(uifig);
dcm.Enable = 'on';
% Step 2: Define a custom UpdateFcn function
% uiax is the handle to the UIAxes
dcm.UpdateFcn = @(hObj,event,ax)localDcmFcn(hObj,event,uiax);
% Step 3: Write the UpdateFcn
% This should be added as an independent function within the app
function txt = localDcmFcn(~,event,ax)
% Compute index
idx = event.Target.CData(event.Position(2),event.Position(1));
% Create output text
txt = sprintf('[X,Y] [%d %d]\nIndex %d\n[R,G,B] [%.4g %.4g %.4g]', ...
event.Position, idx, ax.Colormap(idx,:));
end
Now the datacursor should appear the same in the legacy figure and the uifigure/app. The only difference may be the number of decimal places shown in the RGB values.