Can I change my UIFigure size while maintaining location of elements in figure?

I have a UIFigure that I want to be interactive. There is a dropdown menu, and depending on the number the user selects, new edit field boxes will appear to match that number. I achieve this by adding length to the figure, making the extra editfield boxes visible (they start off as hidden), then re-positioning everything on the bottom half to be closer to the bottom.
The problem is that when I make the figure taller, the length is added to the bottom (this is fine) but when I make the figure shorter, the length is removed from the top. So if the user selects 5, then goes back to select 1, a lot of my items are now out of frame, because I only adjust the position of the items on the bottom half of the figure.
I could just re-position everything within the figure every time I chane the figures size, but there are 51 elements total between all the hidden/visibile labels and buttons and boxes and such, and that is a lot of stuff to reposition.
Is there a workaround I'm not thinking of where I can repeatedly change the size of my figure without messing up the position of everything? Is there a better way to go about this? I'm on 2019b if that matters.

6 Commenti

when I make the figure taller, the length is added to the bottom
What steps do you take to make the figure taller or shorter?
Sorry, should have included that
figHeight = 400; %original figure height
numPools = str2double(NumberOfPoolsDropdown.Value);
position = get(UIFigure, 'Position'); %get current figure position/size
newFigHeight = figHeight - 30 + (numPools*30); %add 30 new pixels in height for each pool
%make figure taller/shorter, maintain the same vertical location of
%the top of the figure
UIFigure.Position = [position(1) (position(2)-(newFigHeight - position(4))) position(3) newFigHeight];
%re-position all the elements below the pool entry edit field boxes
CancelButton.Position = [160 15 100 22];
OKButton.Position = [270 15 120 22];
PlateTypeLabel.Position = [30 150 200 22];
ExampleLabel1.Position = [30 70 120 22];
ExampleLabel2.Position = [140 70 250 22];
PlateTypeRadioGroup.Position = [110 125 130 45];
This works fine when I'm making the figure bigger, I only run into issues when I try to go smaller again.
So to confirm, you make the figure larger by keeping the same vertical position of the top of the figure, but lowering the bottom, and then moving the buttons to be absolute positions relative to the new bottom?
Taking into account that vertical positions are relative to the bottom of the screen, so y coordinates like in cartesian graphs, increasing y coordinate meaning moving up (whereas some graphics systems instead position relative to the top of the screen with increasing y coordinates meaning moving down from the top.)
If this is correct, then anything you have already added to the figure and which you do not reposition explicitly (like the bottoms) and which is not configured in normalized coordinates, should move down: they should be keeping constant distance from the baseline and the baseline is moving down.
Yes you are correct on your first point. But rather than "Lowering the bottom" I think of it as "Increasing the height" but I don't know how to choose if the height is increased at the top of the figure or at the bottom. In my case it looks like "Lowering the bottom" is what occurs, but I didn't specifically choose that. Then at the same time as I increase the height, I move the figure to ensure the vertical position of the top is consistent.
You say things should be keeping a consistent position from the bottom, but that's not what is happening. When I type this (without explicitly repositioning anything) everything stays a constant distance from the top and I get empty space at the bottom of my figure, as seen above in the "Made Figure 1 taller" image:
figPosition = get(UIFigure, 'Position');
UIFigure.Position = [figPosition(1), figPosition(2), figPosition(3), figPosition(4)+100];
When I type this (without explicitly repositioning anything) everything does stay a consistent distance from the bottom, like you say it should, as seen above in the "Made Figure 1 shorter" image:
figPosition = get(UIFigure, 'Position');
UIFigure.Position = [figPosition(1), figPosition(2), figPosition(3), figPosition(4)-100];
In my ideal scenario everything stays a consistent position from the top of the figure, and then I reposition those 6 items every time I resize the figure. Is this possible?
Must the figure itself change size when you change your selection? If not, can you make the maximum number of rows of edit boxes in fixed positions and toggle their visibilities depending on your selection?
@J. Alex Lee Yeah I suppose I could do that. It just makes the figure pretty tall with a lot of blank space. Changing the figure size is classier in my opinion, but if I can't get it to work I can always use that as a last resort.

Accedi per commentare.

 Risposta accettata

I think you may be able to achieve what you want using the uigridlayout, see if this example works on 2019b (I'm on 2022a).
The idea is to use uigridlayout to keep your static stuff positioned how you want, and you would still preallocate the max number of rows for your edit fields, but you can make the inactive grid cell heights zero and then resize the figure
% elements are typically 22 pixels tall
% default spacing/padding in uigridlayout is 10
h = 22;
s = 10;
% lay out a drop down, n edit fields, and a button at the bottom
n = 5;
figHeight = (2+n)*(h+s) + s;
itemsdata = 1:n;
% draw
fig = uifigure();
fig.Position(3) = 200;
fig.Position(4) = figHeight;
uig = uigridlayout(fig,[2+n,1],"Padding",s,"RowSpacing",s,...
"RowHeight","fit"+strings(2+n,1));
uib = uibutton(uig,"Layout",matlab.ui.layout.GridLayoutOptions('Row',2+n,'Column',1),"Text","A button");
for i = n:-1:1
uie(i) = uieditfield(uig,"Layout",matlab.ui.layout.GridLayoutOptions('Row',1+i,'Column',1),"Value","edit "+i);
end
uid = uidropdown(uig,"Layout",matlab.ui.layout.GridLayoutOptions('Row',1,'Column',1),...
"ItemsData",itemsdata,"Items",itemsdata+" edits","Value",n,...
"ValueChangedFcn",@(o,e)ddchangefcn(o,e,uig,fig,h,s) ...
);
function ddchangefcn(src,evnt,uig,fig,h,s)
n = numel(src.Items);
m = src.Value;
RH = cell(1,n);
RH(m+1:n) = {0};
RH(1:m) = {'fit'};
uig.RowHeight = ['fit',RH,'fit'];
fig.Position(4) = (2+m)*(h+s) + s;
end

2 Commenti

@J. Alex Lee Yes yes YES!!! uigridlayout() is exactly what I needed, but I had never heard of it until your answer. Thank you so much!

Accedi per commentare.

Più risposte (0)

Categorie

Scopri di più su Develop Apps Programmatically in Centro assistenza e File Exchange

Prodotti

Release

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by