altmany / export_fig

A MATLAB toolbox for exporting publication quality figures
BSD 3-Clause "New" or "Revised" License
1.28k stars 368 forks source link

Exporting uifigure #261

Closed MarvinILA closed 5 years ago

MarvinILA commented 6 years ago

Hi,

I am trying to use the export_fig code within the Matlab App Designer. I am trying to export the figure with the following code:

export_fig(figureHandle, path2file, '-pdf', '-png', '-m1.5');

However, as I execute the code the following error is shown:

Error using matlab.ui.Figure/set
Functionality not supported with figures created with the uifigure function. For more information,
see Graphics Support in App Designer.

Error in export_fig (line 397)
        set(fig, 'InvertHardcopy', 'off');

How can I run export_fig with uifigures?

Thanks a lot!

altmany commented 6 years ago

Figures created using App Designer or the uifigure command are not supported by export_fig, as long as Matlab does not support the built-in print function with such figures. This is still the case as of R2018b: https://www.mathworks.com/help/releases/R2018b/matlab/creating_guis/graphics-support-in-app-designer.html

There is no possible solution or workaround for uifigures until this changes.

apiccirilli commented 5 years ago

I think this last commit may have broken the ability to specify an individual axes to plot: with a new install of export_fig, you can run this to recreate:

f = figure();
ax = axes();
plot(ax, 1:10, sin(1:10));
export_fig(ax, 'test.png')

which gives you the error:

Undefined function or variable 'jf'.

Error in export_fig (line 298)
        if isempty(jf)

This seems to happen because there is no JavaFrame property for axes, and is fixed by either checking for the existence of jf on line 298 (if exist('jf', 'var') && isempty(jf)) or by adding some logic/assignment to your catch clause there.

Hope that helps, and thanks for maintaining such a great library. Aaron

altmany commented 5 years ago

Fixed, please recheck

apiccirilli commented 5 years ago

All good - thanks!

ghost commented 5 years ago

Thanks for the alert. Does export_fig work with appDesigner in version 2018a?

altmany commented 5 years ago

On Nov 18, 2018 above I wrote "This is still the case as of R2018b", so why are you asking about 2018a?!

export_fig does not work with uifigures (created by AppDesigner or the uifigure command), in any Matlab release. When this will change (if ever), I will post an update.

MarvinILA commented 5 years ago

What you can do, however, is to copy your uifigure into a "standard" figure-window in the background. Use the "copy object" command to copy the uifigure's children into the new figure. Export that copied figure as usual. Maybe some formatting is still required.

ghost commented 5 years ago

I

On Nov 18, 2018 above I wrote "This is still the case as of R2018b", so why are you asking about 2018a?!

export_fig does not work with uifigures (created by AppDesigner or the uifigure command), in any Matlab release. When this will change (if ever), I will let post an update.

I also found that "annotation" does not work. Very frustration after following the AppDesigner route.

alfredoqt commented 5 years ago

@MarvinILA how do yo do that?

MarvinILA commented 5 years ago

@alfredoqt that's pretty easy. Please find below my code. Of course you might have to do some adjustments for your case.

% Convert UIFigure to normal figure
fig = figure('Units', app.YourPlot.Units, 'Position', app.YourPlot.Position, 'InnerPosition', app.YourPlot.InnerPosition, 'OuterPosition', app.YourPlot.OuterPosition);

% Set figure to be invisible
set(fig, 'MenuBar', 'none', 'ToolBar', 'none', 'Visible', 'off');

% Get figure axes
figAxes = axes(fig);

% Get all the children from the UIFigure
allChildren = app.YourPlot.Children;

% Copy all children to the new figure
copyobj(allChildren, figAxes)

% Set axes limits
figAxes.XLim = app.YourPlot.XLim;
figAxes.YLim = app.YourPlot.YLim;
figAxes.ZLim = app.YourPlot.ZLim;

% Modify the legend
lgndName = app.YourPlot.Legend.String;
lgd = legend(YourPlotsToAppearInTheLegend, lgndName);
lgd.Box = app.YourPlot.Legend.Box;
lgd.Location = app.YourPlot.Legend.Location;
lgd.FontSize = app.YourPlot.Legend.FontSize;

% Set axes labels
figAxes.YLabel.String = app.YourPlot.YLabel.String;
figAxes.YLabel.FontSize = app.YourPlot.YLabel.FontSize;
figAxes.XLabel.String = app.YourPlot.XLabel.String;
figAxes.XLabel.FontSize = app.YourPlot.XLabel.FontSize;

% Set title
figAxes.Title.String = app.YourPlot.Title.String;
figAxes.Title.FontSize = app.YourPlot.Title.FontSize;

% Honestly, I don't remeber why I set that color
fig.Color = [1 1 1];

% Export figure
export_fig(fig, biplotFNfull, '-pdf', '-png', '-eps', '-m5');

% Clean up
delete(fig)

Note the following:

Good luck coding!

altmany commented 5 years ago

@MarvinILA - that's a great idea. I'm sorry that I missed it when you first posted it earlier this year. I'll integrate it into export_fig later today/tomorrow.

altmany commented 5 years ago

Fixed.

There are still a few limitations, but I expect them to affect only a very small percentage of users:

  1. only uifigure and uiaxes handles can be specified, but not panel handles as in legacy figures
  2. only a single handle at a time can be exported - not an array of handles as with legacy figures
  3. exporting a combination of uifigure and legacy figure handles is not supported
  4. uicontrols within the uifigures are not exported

Thanks again, @MarvinILA !

Enjoy!

Dev-iL commented 5 years ago

Yair, might I suggest you add a note about the partial support for uifigure to the main README.md? I think your previous reply regarding the print function shouldn't be hidden within some closed bug report.

BTW, I'm experimenting with exporting those figures via webpage-to-pdf JS libraries (like https://github.com/niklasvh/html2canvas and https://github.com/MrRio/jsPDF), but I'm struggling with the limitations TMW keeps imposing on custom JS libraries (despite supposedly allowing them through uihtml).

At the moment one can use hWebWin.executeJS('print()'); if they're fine with dealing with the OS print dialog.

altmany commented 5 years ago

@Dev-iL - done