Getting data from the figure in appdesigner

Hi.
In my app, there is a section that lets user to select multiple points from a figure and later these points will be used to show some results. when I run this app in the matlab appdesigner space, everything works fine, However, when I complie the app by deploytool and create a standalone application,after installing the app and checking it, it doesn't save the selected points. in the picture, the top part is for when running the app within appdedesigner space and the bottom part is when I run it from the windows (after compiling and installing it on my compute). I am using the below code for getting information from a figure.
dcm_obj = datacursormode(fig);
set(dcm_obj,'DisplayStyle','datatip',...
'SnapToDataVertex','off','Enable','on')
pause
c_info = getCursorInfo(dcm_obj)
close gcf
I would really appreciate if anyone can tell me what should I do?
Picture1.jpg

7 Comments

When you say "not saving", do you mean the app doesn't have access to the data, or do you mean not saving a file to disk?
Also, just in case, you are not trying to save data to the matlab workspace are you? I don't know how that would behave when deployed.
Thnaks for your insight Alex. First by save I meant internally not on the disk. But the point that you mention, apprently it sent the data to workspace and because of that nothing happens. However when I complie it in a packegae, not in a standalone way, and add it to my apps tab in matlab, it worked.
Hmm, it seems unlikely that you're inadvertently sending to workspace...as far as I understand you'd need to be invoking assignin(c_info,'WS') or something like that...
So is your package route viable and/or your issue is solved?
Arash
Arash on 6 Feb 2020
Edited: Arash on 6 Feb 2020
Yes, I am not loving the idea, because for working with apps you have to open matlab first, while, in a standalone one you just run it like any other software. But it's good enough for me. again thanks.
Well, we never got to the actual code, but it sounds like you are maybe relying on external scripts rather than functions to do various tasks. Is this right? For example your supplied code snippet in your question is not wrapped in a "function" block? The same must be true for whatever block of code you are calling to do something with that data when you push the button. But this is odd because you're still able to access the separate figure in your deployed app...if you show your code, or at least the structure of your code, or the relevant chunks of code, this seems like it should be an easy problem to solve.
Actually it is my fiirst time to work with appdesigner, it's good thing for students to see the results without getting confuse with coding. That is why I insisted to make a standalone software. But again now the difference is just that they have to open the matlab and go to apps tab and run the app. I am sure, I am not doing things 100% in a professional way. But to answer your question, Yes I break my main code to different functions that each of them does seperate things. when a button is pushed, the function is activated. I hope in future to do it in like Object-oriented way but for now on everything is in functions and the function regarding selecting point is this:
I appreciate your time and suggestions in advance.
function [x,y]=ManuallySelect(Displ,Force);
fig = figure('units','normalized','outerposition',[0 0 1 1]);
plot([0 0],[-max(abs(Force)) max(abs(Force))],'k',[-max(abs(Displ)) max(abs(Displ))],[0 0],'k');hold on;
plot( Displ,Force,'LineWidth',1.1);grid on
dcm_obj = datacursormode(fig);
set(dcm_obj,'DisplayStyle','datatip',...
'SnapToDataVertex','off','Enable','on')
pause
c_info = getCursorInfo(dcm_obj)
close gcf
x=zeros(length(c_info),1);
y=zeros(length(c_info),1);
for i=1:length(c_info);
x(i,:)=c_info(i).Position(1);
y(i,:)=c_info(i).Position(2);
end
end
% The call back in the app:
% Callback function
function ClickMePositiveButtonPushed(app, event)
%Getting the global variable displacement and force
y1=app.Displ;
y2=app.Force;
[x,y]=ManuallySelect(y1,y2);
%saving it in the global propertise of the pp (DbackP and FbackP) to use it later
app.DbackP=x;
app.FbackP=y;
end
I don't see anything wrong structurally, so I was wrong in my assumption.
Admittedly I don't know the getcursorinfo function, as it is in a toolbox I don't have, but I bet the problem is that nothing after calling "ManuallySelect()" is executing within your callback, either because of getCursorInfo itself, or how you are relying on pause().
I'm not sure if there's a better way using debug tools, but you can output something to console like
function ClickMePositiveButtonPushed(app, event)
%Getting the global variable displacement and force
y1=app.Displ;
y2=app.Force;
[x,y]=ManuallySelect(y1,y2);
disp('hi, checking if this executes!')
%saving it in the global propertise of the pp (DbackP and FbackP) to use it later
app.DbackP=x;
app.FbackP=y;
end
and try to catch it in your deployed app by running it via command line.
But yes, it would probably be cleaner to set up a way to respond to click callback's on the plotted object.

Sign in to comment.

Answers (1)

Here's an example where I used the data cursor's update function itself to collect the coordinates and feed directly into your app's DbackP and FbackP properties.
I think it should be easy enough to plug and play into your app.
Does it work?

3 Comments

Unfourtunatly, it was created by a newer version of appdesigner and it says it can not open it, I am using matlab 2017a. when I run the app, this happens. Probably there should be an option to save it for older version.
Alex.jpg
It looks like the offending line was "xline" and "yline", but you were actually able to open/run in your version of app designer otherwise. But I exported to .m as well. Does this work?
The important parts that we have been discussing are to pass the app to the ManuallySelect function so that it has direct access to the DbackP and FbackP properties
function results = ManuallySelect(app,xIn,yIn)
% clear the saved data?
app.DbackP = [];
app.FbackP = [];
app.UITable.Data = {};
app.DataFig = figure(); %'units','normalized','outerposition',[0 0 1 1]);
app.DataFig.CloseRequestFcn = @(src,evnt)CloseDataFig(app,src,evnt);
ax = axes(app.DataFig,'NextPlot','add','XGrid','on','YGrid','on'); % hold on
% if your matlab version supports
try
xline(0);
yline(0);
catch
% better than
plot([0 0],[-max(abs(Force)) max(abs(Force))],'k',[-max(abs(Displ)) max(abs(Displ))],[0 0],'k');
end
plot(ax,xIn,yIn,'LineWidth',1.1);
dcm_obj = datacursormode(app.DataFig);
set(dcm_obj,'DisplayStyle','datatip',...
'SnapToDataVertex','off','Enable','on')
dcm_obj.UpdateFcn = @(src,evnt)dateTipUpdateFcn(app,src,evnt);
end
And in define a new UpdateFcn for the dcm_obj that also has access to the app; in its callback function, keep appending new points and define the tooltip text
function txt = dateTipUpdateFcn(app,src,evnt)
app.DbackP = [app.DbackP;evnt.Position(1)];
app.FbackP = [app.FbackP;evnt.Position(2)];
txt = sprintf('saved point: (%g,%g)',evnt.Position);
app.UITable.Data = num2cell([app.DbackP,app.FbackP]);
end
Just for demo, I also had a uitable that was displaying all of the chosen data in real time.
Now everything is fine Alex. Thank you for all your suggestions.

Sign in to comment.

Categories

Find more on Develop Apps Using App Designer in Help Center and File Exchange

Asked:

on 4 Feb 2020

Commented:

on 10 Feb 2020

Community Treasure Hunt

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

Start Hunting!