Hi!
How do I save a plot I made with UIAxes, ie. NOT with figure - I tried print but it didn't work and I don't understand why. Is there ANYWAY to save a UIAxes plot?
My question is about Appdesigner.

댓글 수: 3

Lydin Camilleri
Lydin Camilleri 2018년 4월 5일
any answer to this pleasE?
shahram maghami
shahram maghami 2019년 3월 24일
no solution yet ?
I've same problem.
farzad
farzad 2020년 4월 2일
did you manage finally ? which one worked for you ?

댓글을 달려면 로그인하십시오.

 채택된 답변

Adam Danz
Adam Danz 2019년 3월 24일
편집: Adam Danz 2019년 10월 24일

4 개 추천

Update: Try using copyUIAxes() from the file exchange.
[original post below]
There's no way to directly save the 'figure' produced by UIAxes in app designer (bummer). An alternative would have been to copy the UIAxes onto a new figure using copyobj(axHand, figHand) which works with axes developed in guide() but that functionality is not supported with UIAxes from app designer (double bummer).
A workaround is, from within your app,
  1. Create a new figure and new axes
  2. Copy the UIAxes children on to the new axes
  3. Copy most of the UIAxes properties over to the new axes
Some axes properties are read-only so we can't copy those over to the new axes. Also, there are some axes properties that you don't want to copy over such as parent, children, X/Y/ZAxis, which will cause errors. In addition to those, you'll see in the code below where I added the "Position" and "OuterPosition" properties to the list of properties not to copy. In your app, the axes are probably small and if you want your new axes to also be the same size, you could remove the two position properties from the 'badFields' list.
% Create new figure and new axes
figure
axNew = axes;
% Copy all objects from UIAxes to new axis
copyobj(app.UIAxes.Children, axNew)
% Save all parameters of the UIAxes
uiAxParams = get(app.UIAxes);
uiAxParamNames = fieldnames(uiAxParams);
% Get list of editable params in new axis
editableParams = fieldnames(set(axNew));
% Remove the UIAxes params that aren't editable in the new axes (add others you don't want)
badFields = uiAxParamNames(~ismember(uiAxParamNames, editableParams));
badFields = [badFields; 'Parent'; 'Children'; 'XAxis'; 'YAxis'; 'ZAxis';'Position';'OuterPosition'];
uiAxGoodParams = rmfield(uiAxParams,badFields);
% set editable params on new axes
set(axNew, uiAxGoodParams)
For trouble shooting, or to loop through each property rather then setting them all at once, replace the last line of the code above with this for-loop below which indicates the property being edited in the command window.
% Set new axis params
allf = fieldnames(uiAxGoodParams);
for i = 1:length(allf)
fprintf('Property #%d: %s\n', i, allf{i});
set(axNew, allf{i}, uiAxGoodParams.(allf{i}))
end
One alternative worth mentioning: Instead of your app hosting the axes, you could program your app to plot the data onto an external figure and then you wouldn't have this problem.

댓글 수: 7

Ahmed Salih
Ahmed Salih 2019년 3월 26일
Thanks for answering, even though the question is more than one years old. I hope someone else will find this useful in the future :-) I've accepted your answer, but have not checked it out since it was a bit of a long time ago I needed it. Thanks again!
Adam Danz
Adam Danz 2019년 3월 26일
Thanks for accepting the answer. I tested this with one of my apps and it works. Maybe in future releases matlab will allow the use of copyobj() from UIAxes to external figure.
Ajeya Gupta
Ajeya Gupta 2019년 4월 22일
Hello Adam Danz
Thanks for your code, and this works well (with a slight problem) in my appdesigner (using Matlab 2018a version).
When I run your code, the data from UIAxes get copied to axNew variable, which generates a .fig equivalent of UIAxes in a new pop up box (like any regular MATLAB code would generate). Are there any more lines that I can on top of your code to create a pop up box to ask the user to save the file at a specific location and the file name?
I tried adding this piece of code at the end of your code:
saveas(gca,uiputfile({'*.png'; '*.fig'; '*.jpg'}));
close Figure 1;
But, the issue with this is the file doesnt get saved at user defined path. Rather, it gets saved in a path from where I import certain files required for certain computations. Additional issue is the .fig file from your code still remains as pop up box, while simultaenously allowing user to enter file name and path name.
Thanks You,
Ajeya Gupta
ax = gca;
[filename, pathname] = uiputfile({'*.png'; '*.fig'; '*.jpg'});
if ~ischar(filename); return; end %user cancel
fullname = fullfile(pathname, filename);
saveas(ax, fullname);
fig = ancestor(ax, 'figure');
close(fig);
Recording the axes is used because the notion of the "current" axes or "current" figure change if the user clicks elsewhere, such as they might well happen to do in the process of deciding which filename to use.
had the same problem when opening the saved fig.
You have to set the figure property 'visible' to "on" again before saving.
% Save Figure
fig2Save = ancestor(ax, 'figure');
fig2Save.Visible='on';
savefig(fig2Save,'myfig.fig')
close(fig2Save);
Sören
Rohit Deshmukh
Rohit Deshmukh 2020년 3월 11일
i am getting this error in this line set(axNew, uiAxGoodParams);
Error using matlab.graphics.axis.Axes/set
Value must be a 1x2 vector of numeric type in which the second element is larger than the first and may be Inf
It works well when XAxisTickTabels are 1,2,3,4... but gives an error when XAxisTickLabels are {'Clipping' } {'NextPlot' } {'Toolbar' } {'Interactions' }
Please guide.

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Will Grant
Will Grant 2019년 5월 2일
편집: Will Grant 2019년 5월 2일

6 개 추천

Inspired by Adam's answer, here is a function you can call directly with slightly enhanced functionality.
Note the addition of calling copyobj() with the title and label objects, and removing them from the set() when transfering property values. Adam's original code re-parents the title and label objects to the new axes. The label objects are still located under the original axes, but their respective label.Parent property is set to axTo, a fairly useless situation.
function myCopyObj(axFrom, axTo)
% Custom version of copyobj() which works to copy a UIAxes object to
% an old-school axes object.
% Copy children (lines).
copyobj(axFrom.Children, axTo);
% Copy titles and labels.
copyobj([axFrom.Title axFrom.XLabel axFrom.YLabel], axTo)
% Transfer other properties.
uiAxParams = get(axFrom);
uiAxParamNames = fieldnames(uiAxParams);
% Get list of editable params in new axis
editableParams = fieldnames(set(axTo));
% Remove the UIAxes params that aren't editable in the new axes (add others you don't want)
badFields = uiAxParamNames(~ismember(uiAxParamNames, editableParams));
badFields = [badFields; 'Parent'; 'Children'; 'XAxis'; 'YAxis'; 'ZAxis'; ...
'Position'; 'OuterPosition'; 'XLabel'; 'YLabel'; 'ZLabel'; 'Title'];
uiAxGoodParams = rmfield(uiAxParams,badFields);
% set editable params on new axes
set(axTo, uiAxGoodParams)
end
To use:
% Define figure and axes to specifications.
f = figure('Visible', false);
axNew = axes(f);
% Copy.
myCopyObj(origUIAxesHandle, axNew);
% Print!
print(f, filePath);
delete(f);

댓글 수: 3

Adam Danz
Adam Danz 2019년 5월 2일
편집: Adam Danz 2020년 2월 3일
Nice work!
But see copyUIAxes() on the file exchange which offers additional features and safetynets.
Namwon Kim
Namwon Kim 2019년 8월 20일
편집: Namwon Kim 2019년 8월 20일
Thanks for your answer, and the code works very well.
I would add on small feature at the top of the function. If the "axTo" is not provided, it should be created within the function. That saves the user from creating the axes if the axes is just a simple, standard axes.
This would go at the top of the function.
% Generate new axes if 2nd input is missing or empty.
if nargin < 2 || isempty(axTo)
fh = figure();
axTo = axes(fh);
end

댓글을 달려면 로그인하십시오.

카테고리

도움말 센터File Exchange에서 Develop Apps Programmatically에 대해 자세히 알아보기

제품

질문:

2017년 11월 23일

댓글:

2020년 4월 2일

Community Treasure Hunt

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

Start Hunting!

Translated by