I have the following MATLAB script:
fig = figure('Position', [150 30 900 600]);
%height = 2100; % Works as expected
height = 2400; % Elements appear in the wrong places
panel = uipanel(fig, 'Units', 'pixels', 'Position', [0 0 900 height]);
xs = linspace(-pi,pi,101);
ys = sin(xs);
width = 300;
height = 300;
yOffset = height*19;
for x = 1:3
for y = 1:2
a = axes(panel, 'Units', 'pixels');
a.Position = [(x-1) * width, (y-1) * height, width, height];
plot(a, xs, ys);
end
end
When run, I expect this to create a figure containing a panel and 6 tiled axes that should fill the entire figure window. Instead, the axes elements appear to be shifted up, and partially off, of the panel and figure. This looks like:
If I change height to a lower number, such as 2100, I get what I expect:
Since positions are relative to the bottom left corner, I don't see why changing the height would make the axes elements move like this. It isn't a smooth transition, if the height isn't too high, the axes are in the right place, but once the height is too high, further increases in height cause the axes to move further and further up the window.
I am using MATLAB R2017a. Am I doing something wrong? What is the cause of this?
Note: I am aware that my panel is much bigger than the figure, this is intentional and desired for my application.
Related
One can easily use the Position property to place a uifigure in the specified location of the screen. E.g., fig = uifigure('Position',[1,1,300,300]);. Is there any way to place it immediately on the center of screen.
There is a movegui command which is helpful for this task. However, it does this work in two steps (first, displays the figure, then moves it). This results in a not smooth experience for the user.
We need to get the screen size to determine the center. The code below will create a figure at the center of the screen.
% width and height of the figure
width = 300;
height = 300;
% screen size
sz = get( 0, 'ScreenSize');
% center position
x = mean( sz( [1, 3]));
y = mean( sz( [2, 4]));
fig = uifigure( 'Position', [x - width/2, y - height/2, width, height])
Use
movegui(app.UIFigure,'center')
Consider the simple code below that generates a straight downward sloping line in MATLAB.
clear, clc, close all
t = 0:0.1:1;
y = -t+1;
plot(t,y)
ax = gca
This is a line with slope -1, so the (acute) angle between the horizontal axis and the line is 45 degrees. Except it isn't when you measure with a protractor on your monitor.
Without changing the range of values displayed on the x and y axes or the height of the figure window, how could I ensure I would measure 45 degrees from the horizontal axis to the line if I held a protractor up to the screen?
My current approach is to change the width of the figure window. In the limit as the figure window is infinitely thin, the line x is a vertical line. Conversely, if the figure window is stretched to the edges of a monitor, it flattens out. Somewhere in the middle, the line has the angle I want. I just can't find a good way to mathematically find this point and instantiate it in code.
Edit: A slightly more generic solution for any acute angle. (I didn't test obtuse angles.)
clear, clc, close all
ang_deg = 70;
slope = tand(ang_deg);
t = 0:0.1:1;
y = -slope*t+1;
f = figure;
f.Position(3) = f.Position(3)*1.5;
plot(t,y)
% For a given height, change the width
ax = gca;
ax.Units = 'pixels';
ax.Position(3) = ax.Position(4)/slope;
You can achieve that with
axis equal
which, according to the documentation,
uses the same length for the data units along each axis.
You may want to also use
axis tight
which
fits the axes box tightly around the data by setting the axis limits equal to the range of the data
Follow up your commands with a declaration that you'll be working in pixels, and then set the width to the height:
ax.Units = 'pixels';
ax.Position(3) = ax.Position(4);
How to know the exact size and position of the axis box (without axis labels and numbers)? For example, if I use
figure
contourf(x,y,u,100,'linestyle','none')
axis equal
set(gca,'position',[0.1,0.1,0.7,0.8]) %normalized units
The size of the axis frame/box is varyed in the case of the figure window resizing (or using axis equal), but the value of get(gca,'position') remains unchanged. For example:
figure
Z = peaks(20);
contourf(Z,10)
set(gca,'Units','pixels')
get(gca,'position')
axis equal
get(gca,'position')
ans =
0.1300 0.1100 0.7750 0.8150
after axis equal, the axis box is changed, but get(gca,'position') gives the same coordinates:
ans =
0.1300 0.1100 0.7750 0.8150
I need these to align the colorbar to the axis box (with fixed gap between them) in the case of axis equal.
When you call axis equal, the axis box aspect ratio is fixed and the Position property is treated as a maximum size. When you resize the figure window, the axis box will remain centered in the Position rectangle, but in order to maintain the same aspect ratio as before, it may not take up the entire Position rectangle.
If you want it to take up the entire Position rectangle, you can call axis equal again. (this may depend on your MATLAB version; it worked for me in R2015b).
This is also discussed in a bit more detail on MATLAB Central.
To answer your original question, it's a bit complicated. You'd have to get the plot box aspect ratio (using pbaspect() or the axes PlotBoxAspectRatio property) and figure it out:
ah = gca();
% Get the axes Position rectangle in units of pixels
old_units = get(ah,'Units');
set(ah,'Units','pixels');
pos = get(ah,'Position');
set(ah,'Units',old_units);
% Figure the PlotBox and axes Position aspect ratios
pos_aspectRatio = pos(3) / pos(4);
box_aspect = pbaspect(ah);
box_aspectRatio = box_aspect(1) / box_aspect(2);
if (box_aspectRatio > pos_aspectRatio)
% PlotBox is wider than the Position rectangle
box_height = pos(3) / box_aspectRatio;
box_dy = (pos(4)-box_height) / 2;
box_position = [pos(1), pos(2)+box_dy, pos(3), box_height];
else
% PlotBox is taller than the Position rectangle
box_width = pos(4) * box_aspectRatio;
box_dx = (pos(3)-box_width) / 2;
box_position = [pos(1)+box_dx, pos(2), box_width, pos(4)];
end
Note that this will give you the box position in pixels; if you want it in the normalized units that are the axes default, you'll need to normalize it:
fig_pos = get(get(ah,'Parent'),'Position');
box_position = box_position ./ fig_pos([3 4 3 4]);
Simple question: How do you get the current figure size in MATLAB?
Example:
figure(1)
[width, height] = ****some function I'm not aware of****
Googling this always returns how to change the window size but not how to just get the current window size.
Any help is appreciated.
Cheers
pos = get(gcf, 'Position'); %// gives x left, y bottom, width, height
width = pos(3);
height = pos(4);
I would like to programmatically (or in GUIDE) fix the matlab-uitable to be the whole width of the panel on initialisation. How can I do this?
All I've managed is to change the size in pixels of single columns. I would like the uitable to be 100% the width of the page at that time. When my window is in minimized form the GUI looks fine, but when I maximize it, the uitable is only about half the width of the page. (The uitable's height is not that of the whole panel though, around 1/2 of the whole page)
The GUI is written in matlab-guide.
This is the code that I am trying right now:
data = populateTable;
parentPosition = get(handles.uipanel4, 'position');
uitablePosition = [x y parentPosition(3)-2 parentPosition(4)-2];
set(handles.uitable, 'Position', uitablePosition);
set(handles.uitable, 'Visible', 'on');
set(handles.uitable, 'Data',data, 'ColumnFormat',{'numeric'});
A possible solution could be to set both the position of the figure and of the table to normalized, then to set the position of the table to [0 0 1 1]
f = figure
set(f,'unit','normalized')
set(f,'position',[0.1 0.1 0.5 0.5])
data = rand(13);
for i=1:length(data)
col_names{i}=['Col. # ' int2str(i)];
end
for i=1:length(data)
row_names{i}=['Row. # ' int2str(i)];
end
t = uitable(f, 'Data', data,'unit','normalized', ...
'Position', [0 0 1 1],'columnname',col_names, ...
'rowname',row_names);
You need to set the uitable's position property when you initialize it.
First, get the position of the uitable's parent object. That could be a uipanel or a figure. Assume hParent is a handle to the uitable's parent.
parentPosition = get(hParent, 'position');
Then, create your position vector for the new uitable, and use the parent's width and height. You might want to subtract a few pixels for padding. I'll subtract two pixels here.
uitablePosition = [x y parentPosition(3)-2 parentPosition (4)-2];
You can probably set x and y to 1 or 2 as well, depending on where the table is positioned.
uitable( ... 'units','pixels','position', uitablePosition )
You can implement the same idea in your figure's resize function.