How to resize figure without moving contents
10 views (last 30 days)
To standardized my figure export process I use a custom defined printfigs.m call at the end of each script. One of the key things it does is timestamp and add a path to each figure at the top so that I can have a record of which script generated which figure.
To prevent this from overlapping any title's, annotations, or other parts of the figure, I want to resize the figure by adding a margin to the top that I can then use to place my annotation without potentially obstructing anything in the figure. I want a code that can take any figure and stretch the margins without disturbing it's contents.
To accomplish this, I've written this little code which I've been using for the bast two years on 2016b with little issue, but now it fails in 2018b quite frequently.
function  = resizeFig(t, l, b, r)
fh = gcf();
set(findall(fh,'-property','Units'),'Units', 'pixels'); %%Set Object Sizes to Pixels
set(fh,'position',get(fh,'position')+[0,0,l+r,t+b]); % extends range of figure only
%%Grab Re-Sizeable Objects
objs = findobj(fh,'-property','position'); % grabs all objects with position properties
oPos = get(objs,'position'); % grabs position of moveable objects
ind = cellfun(@(C) size(C,2)==4,oPos); % finds objects that take 4 vector position input
objs = objs(ind);
oPos = oPos(ind);
%%Resize Objects within Figure
nPos = cellfun(@(C) C+[l,b,0,0],oPos,'uniformoutput',false); % displace positions left and down
for i = 1:length(objs)
%%Set objects back to normalized/rescaleable
Now I do hope there is a smarter way to do this to improve performance, but more importantly the line:
oPos = get(obs,'position');
tends to fail with this error:
Error using matlab.graphics.Graphics/get
No public property 'Position' for class
this surprises me since the previous line is purposefully chosen to define objs as only those with the position property, though it now complains that it doesn't have that property. The same occurs if I use findall instead of findobj.
What has changed since 2016b and 2018b to cause this to fail?
Greg on 10 Oct 2018
Edited: Greg on 10 Oct 2018
Two things are actually happening. The first is somewhat nitpicky: there is no public property Position for the ToolbarStateButton. The use of findobj is allowed to see the existence of the (let's assume private) property Position, but your use of set is not allowed because it must be public to be set.
The second thing that happened is R2018b introduced some improved (?) (I think so, but you likely disagree right now) axes interaction default functionality. Most of the simple interactions are now ToolbarStateButton objects in a fancy floating-and-auto-appearing axes toolbar, instead of static buttons in the figure toolbar. These new ToolbarStateButton objects apparently have the non-public Position property.
Note: In my tests, findobj did not return the ToolbarStateButton components. I had to use findall.
To fix your code, simply delete the toolbar.
addToolbarExplorationButtons(fh); % Put the old menu buttons back just in case you need them
delete(ah.Toolbar); % ah is an axes handle in the figure