How can I save a figure within app designer?

조회 수: 454 (최근 30일)
J. Webster
J. Webster 2016년 4월 27일
댓글: Rolando Paz Herrera 2023년 1월 24일
I've developed an application using the new App Designer. I'd like to have users be able to click a button and save a figure to a .fig file, or some other image format.
function ButtonSaveFigureButtonPushed(app)
newfigure = figure;
copyobj(app.UIAxesAP, newfigure);
hgsave(newfigure, 'testFIgure.fig');
end
But that gave me the error...
Error using matlab.ui.control.UIAxes/copyElement (line 1219)
Functionality not supported with UIAxes. For more information, see Graphics Support in App Designer.
What's the best way to go about this?
  댓글 수: 6
Ankush
Ankush 2022년 9월 14일
@Saurabh Chaudhary how did you save the .fig file of the uifigure?
Saurabh Chaudhary
Saurabh Chaudhary 2022년 9월 16일
Yes, I had saved the figure. When the figure pops-up you need to go to the file menu and select save as to save it at desired place.

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

채택된 답변

David
David 2018년 4월 4일
편집: David 2018년 4월 4일
I spent some time on this for my own purposes. The trick is to save the individual values from the figure into local variables to be used in a figure as follows:
h = figure;
h.Visible = 'off';
x = UIAxes.XAxis.Parent.Children.XData;
y = UIAxes.XAxis.Parent.Children.YData;
plot(x,y)
lgndName1 = UIAxes.Legend.String{1};
lgd = legend(lgndName1);
lgd.Box = UIAxes.Legend.Box;
lgd.Location = UIAxes.Legend.Location;
h.CurrentAxes.YLabel.String = UIAxes.YLabel.String;
h.CurrentAxes.YLabel.FontSize = UIAxes.YLabel.FontSize;
h.CurrentAxes.XLabel.String = UIAxes.XLabel.String;
h.CurrentAxes.XLabel.FontSize = UIAxes.XLabel.FontSize;
h.CurrentAxes.Title.String = UIAxes.Title.String;
h.CurrentAxes.Title.FontSize = UIAxes.Title.FontSize;
h.CurrentAxes.XLim = [0 max(x)];
h.CurrentAxes.XLim = [0 max(y)+1];
saveas(h,SaveName,'jpg')
savefig(h,SaveName)
delete(h)
Notice I have the visibility off, because I don't want the user to see this going in the background.
Note: You will have to change "UIAxes" to whatever you've named your UI figure
You could also add more properties, but you will have to go into your figure and find the object name to use.
I hope this helps.
Edit: I should also mention that to get this to work as function, I had to make it a call function in a separate .m file. I made a function SaveFigures(UIAxes, SaveName) that is called when ButtonSaveFigureButtonPushed. I have multiple possible plots, which is why I allow the UIAxes to vary. (I use a switch case to make sure I save the correct plot.)
  댓글 수: 7
NE
NE 2019년 3월 5일
Just a quick remark on otherwise very useful reply:
h.CurrentAxes.XLim = [0 max(y)+1];
Shouldn't that be
h.CurrentAxes.YLim = [0 max(y)+1];
Eric Sargent
Eric Sargent 2020년 12월 9일
As of R2020b copyobj supports copying a UIAxes object.

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

추가 답변 (14개)

Joost
Joost 2018년 10월 2일
편집: Joost 2018년 10월 3일
Inspired by David's answer , I came up with this solution which I believe is more generic. My UIAxes contains a lot of graphics objects (mostly patch objects) which are all copied to a temporary figure and then saved. I took over some UIAxes properties (axes limits and data aspect ratio), but you can add any other property you need there. Specify fileName yourself. I put a button called 'Snapshot' in the app with a callback that contains the code below. Matlab R2018a was used.
% Create a temporary figure with axes.
fig = figure;
fig.Visible = 'off';
figAxes = axes(fig);
% Copy all UIAxes children, take over axes limits and aspect ratio.
allChildren = app.UIAxes.XAxis.Parent.Children;
copyobj(allChildren, figAxes)
figAxes.XLim = app.UIAxes.XLim;
figAxes.YLim = app.UIAxes.YLim;
figAxes.ZLim = app.UIAxes.ZLim;
figAxes.DataAspectRatio = app.UIAxes.DataAspectRatio;
% Save as png and fig files.
saveas(fig, fileName, 'png');
savefig(fig, fileName);
% Delete the temporary figure.
delete(fig);
  댓글 수: 12
jichen guo
jichen guo 2019년 10월 23일
Hi Stevan,
Okay, I understand and sorry for the trouble.
Adam Danz
Adam Danz 2019년 10월 24일
Thanks, Joost !

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


Adam Danz
Adam Danz 2019년 3월 24일
편집: Adam Danz 2020년 12월 21일
How can I save a figure within app designer?
Matlab r2016a or later
copyUIAxes(handle,parent) from the file exchange copies the content of uiaxes, and the legend and colorbar if requested, to a new figure. It's a substitute for Matlab's copyobj() which does not support uiaxes prior to r2020b.
% Example
fig = figure();
h = copyUIAxes(app.UIAxes, fig);
Alternatively, use a 3rd party app for screenshots.
Matlab r2020a or later
exportgraphics(obj,filename) stores a snapshot of a graphics object (axes or figure) to an image file (jpg,png,tiff,pdf,emf,eps,+more).
% Example
exportgraphics(app.UIFigure,'C:\Users\name\Documents\Matlab\AppImage.png')
copygraphics(obj) copies a snapshot of a graphics object (axes or figure) to the system's clipboard for each copy-paste.
Matlab r2020b or later
Options (see this Community Highlight for a review)
copyobj(handle,parent) copies a graphics handle, including uiaxes in r2020b+, to a parent.
% Example
fig = figure();
copiedAxes = copyobj(app.UIAxes, fig);
exportapp(fig,filename) exports a UIFigure to a an image file (JPEG, PNG, TIFF, or PDF).
% Example
exportapp(app.UIFigure, 'C:\Users\name\Documents\Matlab\AppImage.png')
F = getframe(ax) or F = getframe(fig) captures the axes or figure as it appears on the screen as a movie frame. getframe() has been around for a long time but its support for uifigures started in r2020b.
% Example
F = getframe(app.UIFigure);
fig = figure();
imshow(F.cdata,'Parent',fig)
This answer has been updated. The original answer is in a comment below.
  댓글 수: 7
Adam Danz
Adam Danz 2020년 4월 21일
편집: Adam Danz 2020년 4월 21일
Thanks for the feedback, Ramu Pradip. I'll think about implementing yyaxis functionality in copyUIAxes.
In the mean time, here's a simple way to use copyUIAxes with yyaxis plots. It copies the left and right axes individually (creating two axes on top of eachother).
% Create yyaxis plot within uiaxes
fig = uifigure();
ax = uiaxes(fig);
yyaxis(ax, 'left')
plot(ax, 1:5, rand(1,5), '-')
ylabel(ax, 'left')
yyaxis(ax, 'right')
plot(ax, 1:.2:5, rand(1,21), 'o')
ylabel(ax, 'right')
xlabel(ax, 'x axis')
title(ax, 'Title')
% Copy left and right axes to the same figure
newFig = figure;
yyaxis(ax, 'left')
axLeft = copyUIAxes(ax, newFig);
yyaxis(ax, 'right')
axRight = copyUIAxes(ax, newFig);
% Make some changes to the right axes
axRight.axes.Color = 'none'; % make transparent
axRight.axes.XTick = []; % remove duplicate x-ticks
axRight.axes.XLabel = []; % remove duplicate x-label
axRight.axes.Title = []; % remove duplicate title
Megan Renny
Megan Renny 2022년 5월 4일
@Adam Danz Thank you so much for your answer to this question!
Your code snippet
% Create new figure and new axes
figure
axNew = axes;
% Copy all opjects from UIAxes to new axis
copyobj(app.UIAxes.Children, axNew)
Works for app designer axes in 2020b that have a left and right hand y axis as well!

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


Guilherme Salgado Braga
Guilherme Salgado Braga 2018년 2월 24일
According to the R2017b documentation on: https://www.mathworks.com/help/matlab/creating_guis/graphics-support-in-app-designer.html
Functions saveas and savefig are not yet supported.

Chao Gong
Chao Gong 2019년 6월 19일
Hi,
Found the issue of this problem. it's because the 'Visible' property is set 'off'. A workaroudn is as below.
--------
This is not currently possible in MATLAB.
As a workaround, please specify 'visible' option when calling 'openfig' to open the figure after it has been saved.
You can also set the "CreateFcn" property of the figure to a function which sets the "Visible" property to on. This allows you to save the figure when invisible but always make it visible when opening it later.
hFig = figure('Visible', 'off');
plot(1:10)
% Set CreateFcn callback
set(hFig, 'CreateFcn', 'set(gcbo,''Visible'',''on'')');
% Save Fig file
savefig(hFig, 'savedFigure.fig')
  댓글 수: 1
Rolando Paz Herrera
Rolando Paz Herrera 2023년 1월 24일
Thanks, I just left visivility 'on' and it worked for me.

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


Dharmendra Sharma
Dharmendra Sharma 2018년 6월 15일
편집: Dharmendra Sharma 2018년 6월 15일
This is the one potential solution which works for me. First, plot the figure/figures in normal way without using uifigure for example see code below. Visibility is on in the following example-
figure('Name','Acc','NumberTitle','off','units','normalized','outerposition',[0 0 1 1])
Then create a separate matlab function file (and call that matlab function from matlab ui). the function may include code to extract figure properties and save the figures as png file. The following link explains the saving all the figures and the code as well-- see the link--
It just need some modifications and I included these in follwoing code-
function [] = handleFigures()
result = isfolder('figures');
if result==0
mkdir figures;
else
delete('figures/*.*')
end
FolderName = 'figures'; % Your destination folder
FigList = findobj(allchild(0), 'flat', 'Type', 'figure');
for iFig = 1:length(FigList)-1
FigHandle = FigList(iFig);
FigName = get(FigHandle, 'Name');
saveas(FigHandle, fullfile(FolderName, [FigName, '.png']))
end
disp('closing figures');
close all
end

Chao Gong
Chao Gong 2019년 6월 19일
Hello David:
I am using the same method answer by you David on 4 Apr 2018. However, I tried to open the saved .fig files afterwards using Matlab, but it doesn't open or respond. The .png files are saved nicely.
Do you encounter similar problem? Is there any possible reason why the saved .fig can't be open?
Thanks

Eric Sargent
Eric Sargent 2020년 12월 9일
As of R2020b copyobj supports copying a UIAxes object.

Thamer Al-Zuriqat
Thamer Al-Zuriqat 2020년 12월 20일
Improved answer inspired by David and Joost , which is technically a combination of both solutions.
fig = figure;
fig.Visible = 'off';
figAxes = axes(fig);
% Copy all UIAxes children, take over axes limits and aspect ratio.
allChildren = app.UIAxes.XAxis.Parent.Children;
copyobj(allChildren, figAxes)
figAxes.XLim = app.UIAxes.XLim;
figAxes.YLim = app.UIAxes.YLim;
figAxes.ZLim = app.UIAxes.ZLim;
figAxes.DataAspectRatio = app.UIAxes.DataAspectRatio;
lgndName1 = app.UIAxes.Legend.String{1};
lgd = legend(lgndName1);
lgd.Box = app.UIAxes.Legend.Box;
lgd.Location = app.UIAxes.Legend.Location;
fig.CurrentAxes.YLabel.String = app.UIAxes.YLabel.String;
fig.CurrentAxes.YLabel.FontSize = app.UIAxes.YLabel.FontSize;
fig.CurrentAxes.XLabel.String = app.UIAxes.XLabel.String;
fig.CurrentAxes.XLabel.FontSize = app.UIAxes.XLabel.FontSize;
fig.CurrentAxes.Title.String = app.UIAxes.Title.String;
fig.CurrentAxes.Title.FontSize = app.UIAxes.Title.FontSize;
% Save as png and fig files.
saveas(fig, fileName, 'png');
savefig(fig, fileName);
% Delete the temporary figure.
delete(fig);

J. Webster
J. Webster 2016년 4월 28일
anybody??
  댓글 수: 1
Tausif
Tausif 2017년 3월 10일
did u get a solution yet? I was looking to do the same

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


Tobias Daßler
Tobias Daßler 2017년 12월 20일
I used a workaround:
saveas(gca,uiputfile({'*.png'; '*.fig'; '*.jpg'}));
close Plot;
Maybe you could adapt this for your problem.
  댓글 수: 2
Eric Long
Eric Long 2018년 6월 4일
Was this used in App Designer?
Adam Danz
Adam Danz 2019년 3월 24일
Functionality not supported with figures created with the uifigure function. So, this doesn't work with axes created in app designer.

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


Craig Pearson
Craig Pearson 2018년 1월 8일
I'm having a similar problem and would like a solution. I was trying to use the print function to copy a figure to the clipboard.
Annoyingly, if I use debugging mode, once the figure is created I can quit debugging mode then use
print -dmeta
from the command window and it proceeds fine - I can then paste this into Excel from the command line (which is what I'm aiming to do from within the app).
Why can this not be achieved from within the App?

Blanca Larraga
Blanca Larraga 2018년 6월 4일
Is there a solution for saving the axes plot in a .jpeg format or not yet? I am trying to insert what I got un an axes figure within a report automatically in app designer but I don't manage to do so. Thanks.

Jyothi Karri
Jyothi Karri 2018년 7월 20일
I have the same issue. Cannot export a UIAxes from gui created from app designer. copyobj did not work either.
  댓글 수: 1
Udo Schröder
Udo Schröder 2018년 8월 13일
I have the same issue. It would help if there would be a nice option just to map an UIAxes element into a normal (pop-up) figure. Then the figure could be saved with the common tools.

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


Paramjeet Panwar
Paramjeet Panwar 2018년 10월 15일
My current workaround is identifying the pixel position of the UIFigure and UIAxes on the screen and taking a snapshot using Java libraries.
Refer to these links -
2 Using Java library for screenshot - this link

카테고리

Help CenterFile Exchange에서 Printing and Saving에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by