How can I save a figure within app designer?
Ältere Kommentare anzeigen
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.
Following the accepted answer at http://www.mathworks.com/matlabcentral/answers/86693-save-axes-plot-as-fig-in-a-gui I tried...
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 Kommentare
Devin Crawford
am 4 Okt. 2017
Based on the number of recent views this is still an open issue. I have the same problem/question using R2017a.
Eric Sargent
am 9 Dez. 2020
As of R2020b copyobj supports copying a UIAxes object.
Saurabh Chaudhary
am 27 Dez. 2021
Bearbeitet: Saurabh Chaudhary
am 27 Dez. 2021
Thankyou @J. Webster, @Adam Danz and @Eric Sargent. I have used the code given in the question in my application and able to save the .fig file. But how to use this to save the .fig file to a specified location with different names.
Use fullfile along with sprintf.
Example:
mypath = cd(); % using current directory for demo purposes
newFile = fullfile(mypath, sprintf('FigNumber%d.fig',1))
Ankush
am 14 Sep. 2022
@Saurabh Chaudhary how did you save the .fig file of the uifigure?
Saurabh Chaudhary
am 16 Sep. 2022
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.
Akzeptierte Antwort
Weitere Antworten (14)
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 Kommentare
Frederic Lenz
am 9 Jan. 2019
Hi Joost,
thanks for sharing your code. If i understand you right, it addresses my problem of multiple graphical objects like two plots in the same UIAxes.
So i copied your Code and choose the 'add' option on 'NextPlot' on the chosen UIAxes in the 'Multiple Plots' Tab within the poperties (I don't know, if it makes a difference, though).
After running it, it came out to be like the result of David's Code, as you can see in the pictures.
In the programming, i used the yyaxis (left/right) command for plotting those two data with their own axis and it clearly just took the last data (yyaxis right) to be saved in the .png.
Can you help me?
Joost
am 22 Jan. 2019
Hello Frederic,
I looked into it but unfortunately I cannot figure out the data structure hierarchy in case of multiple y axes using yyaxis. I hope someone else can help you.
Best regards, Joost
David Mabwa
am 6 Sep. 2019
Hi Joost,
Thank you for your answer, it worked perfectly in most parts, however I am having difficulty adding the legend to the saved image.
Might you have a solution for doing this?
Thanks in advance.
Best Regards,
David
David Mabwa
am 6 Sep. 2019
Hi Joost,
Please ignore, I have managed to sort it out. I used the example in the first answer. Don't know how I missed that.
Thanks,
David
jichen guo
am 20 Okt. 2019
Hi David & Hi Joost,
I am new to appdesigner in MATLAB. I applied Joost's answer, I can save the figure, but I lose the information of xlabel,ylabel,title and legend. Any idea on solving this problem?
Many thanks in advance!
Jichen
Joost
am 21 Okt. 2019
Hi Jichen,
Extending my answer above, I think you can do it like this for the xlabel, ylabel and title:
figAxes.XLabel.String = app.UIAxes.XLabel.String;
figAxes.YLabel.String = app.UIAxes.YLabel.String;
figAxes.Title.String = app.UIAxes.Title.String;
The legend is more difficult, can not be copied in one go. But we can do something like this:
First create a legend object:
legend(figAxes)
Not all properties of the legend object are writable, I will show here how to copy some of them to the new legend.
figAxes.Legend.String = app.UIAxes.Legend.String;
figAxes.Legend.Location = app.UIAxes.Legend.Location;
I hope this helps.
Best regards,
Joost
jichen guo
am 22 Okt. 2019
Hi Joost,
Thanks for your answer and it works! I am really appreciated your help!
Btw, I also find a good answer recently.
I tried that code , it also works fine, but the only problem is that the new printed figure loses the information of legend. Do you have any idea on how to solve this problem? Many thanks in advance!
Best regards,
Jichen
Adam Danz
am 22 Okt. 2019
That answer now includes instructions for copying the legend. :)
Steven Lord
am 23 Okt. 2019
jichen guo flagged Joost's answer and comment from 21 Oct 2019 at 6:26 each with "Best answer I have ever seen for this question!".
jichen guo, please use flags to alert people with the appropriate privilege levels (enough reputation) to spam and other content that's not appropriate for MATLAB Answers. To offer encouragement or praise, please leave a comment. Thanks.
I've cleared both flags.
Joost
am 23 Okt. 2019
Thank you Steven.
Ans thanks for the praise Jichen.
Adam, nice work! Good that we can learn from each other and keep improving in this community.
jichen guo
am 23 Okt. 2019
Hi Stevan,
Okay, I understand and sorry for the trouble.
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
copyobj(handle,parent) copies a graphics handle, including uiaxes in r2020b+, to a parent.
% Example
fig = figure();
copiedAxes = copyobj(app.UIAxes, fig);
% 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.
8 Kommentare
jichen guo
am 22 Okt. 2019
Hi Adam Danz,
I have tried your code, it works fine, but the only problem is that the new printed figure lose the information of Legend. Have you noticed and solved this problem? I am looking forward to your reply. Many Thanks in Advance!
Best regards,
Jichen
original answer
Here's a more general solution that 1) copies all objects onto new external axes and then 2) copies most of the UIAxes properties on to the new axes. This last step is what's missing from the solutions proposed to date.
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 positoin properties from the 'badFields' list.
% Create new figure and new axes
figure
axNew = axes;
% Copy all opjects 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.
[addendum] : copying legend
In app designer, the legend handle is stored within the axis handle structure in app.UIAxes.Legend. The legend has its own set of properties so to copy the legend, you follow the same process as above but there are a different set of problematic properties to remove prior to copying.
% Create new legend
legNew = legend(axNew);
% Save all parameters of the old legend
legParams = get(app.UIAxes.Legend);
legParamNames = fieldnames(legParams);
% Get list of editable params in new legend
editableLegParams = fieldnames(set(legNew));
% Remove the legend params that aren't editable in the new legend (add others you don't want)
badLegFields = legParamNames(~ismember(legParamNames, editableLegParams));
badLegFields = [badLegFields; 'Parent'; 'Children'; 'Position'; 'UIContextMenu'];
legGoodParams = rmfield(legParams,badLegFields);
% set editable params on new legend
set(legNew, legGoodParams)
jichen guo
am 23 Okt. 2019
Hi Adam,
It works! Thank you very much!
Best regards,
Jichen
Adam Danz
am 24 Okt. 2019
@jichen guo, If you're using the approach from my answer, I suggest using the copyUIAxes() function I created which is an improved version of my answer. I'd be glad to get your feedback.
Ramu Pradip
am 21 Apr. 2020
copyUIAxes was doing the trick! Thanks, but with 2 Y axes only one is copied to the new figure.
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
am 4 Mai 2022
@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!
Kristoffer Walker
am 5 Nov. 2024
Thanks Adam!!!
Guilherme Salgado Braga
am 24 Feb. 2018
3 Stimmen
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
am 19 Jun. 2019
2 Stimmen
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 Kommentar
Rolando Paz Herrera
am 24 Jan. 2023
Thanks, I just left visivility 'on' and it worked for me.
Dharmendra Sharma
am 15 Jun. 2018
Bearbeitet: Dharmendra Sharma
am 15 Jun. 2018
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
am 19 Jun. 2019
1 Stimme
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
am 9 Dez. 2020
1 Stimme
As of R2020b copyobj supports copying a UIAxes object.
Thamer Al-Zuriqat
am 20 Dez. 2020
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
am 28 Apr. 2016
0 Stimmen
1 Kommentar
Tausif
am 10 Mär. 2017
did u get a solution yet? I was looking to do the same
Tobias Daßler
am 20 Dez. 2017
I used a workaround:
saveas(gca,uiputfile({'*.png'; '*.fig'; '*.jpg'}));
close Plot;
Maybe you could adapt this for your problem.
Craig Pearson
am 8 Jan. 2018
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
am 4 Jun. 2018
0 Stimmen
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
am 20 Jul. 2018
0 Stimmen
I have the same issue. Cannot export a UIAxes from gui created from app designer. copyobj did not work either.
1 Kommentar
Udo Schröder
am 13 Aug. 2018
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
am 15 Okt. 2018
0 Stimmen
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 -
Kategorien
Mehr zu Creating, Deleting, and Querying Graphics Objects finden Sie in Hilfe-Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!