How to align axes in AppDesigner

6 次查看(过去 30 天)
Hi Folks,
In AppDesigner, is there a simple way to code up a PlotAll(app) function that can easily align vertically the x-axes for vertically stacked axes that have the same "Position" coordinates? For example, below is an example where I have three aligned UIAxes that have the same pixel horizontal positions and thicknesses, but when I plot, the axes labels and the magnitude of the y-axis data values end up causing the plot internal axes to reposition themselves and be mis-aligned.
Thank you,
Kris
  4 个评论
Kristoffer Walker
Kristoffer Walker 2024-12-7
If there were only a function or property I could call on that would position only the axes box frame (ignoring labels, color bars, etc), that would be perfect.
Kristoffer Walker
Kristoffer Walker 2024-12-8
编辑:Kristoffer Walker 2024-12-8
Here is some code that shows how I am trying to use "PositionConstraint", but it does not seem to be working as I am expecting. To put it precisely, "PositionConstraint" has not impact on alignment at all in my code below. If I remove the "reset" calls, the alignment improves a little bit, but the vertical lines that constitute the y-axes in the plots that have the same X Position coordinates and widths are clearly misaligned. Any tricks or usage models out there that have worked for people in AppDesigner I would appreciate hearing, because this is the one thing that keeps making my GUIs look unprofessional.
% In Startup Callback:
app.UIAxesBaro.PositionConstraint = "innerposition";
app.UIAxesNETEN.PositionConstraint = "innerposition";
app.UIAxesNWTEN.PositionConstraint = "innerposition";
% In my PlotAll(app) function that is called when I update the
% GUI plots
% Plot barometric pressure axes
h = app.UIAxesBaro;
cla(h, "reset");
h.PositionConstraint = "innerposition";
yyaxis(h, "left");
h2=plot(h, x, y,sty,'linewidth', ...
app.WidthEditField.Value,'tag','Baro'); % in kPa
if (~app.BaroCheckBox.Value) h2.Visible = "off"; end;
ylabel(h, 'Barometric Pressure (kPa)');
[tOut, dOut, tOut_UTC] = FindPressTimeWindow(app, yr, jd, hr, mn, sc, tdur);
yyaxis(h, "right");
h2 = plot(h, tOut_UTC, dOut(:,15), 'tag','press','linewidth', app.WidthEditField.Value);
if (~app.PressCheckBox.Value)
for j = 1:length(h2)
h2(j).Visible = "off";
end
end
yyaxis(h, "right");
ylabel(h, 'Injection Pressure (kPa)');
xlabel(h, 'Time');
title(h, 'Site Data');
h = app.UIAxesNWTEN;
cla(h, "reset");
h.PositionConstraint = "innerposition";
yyaxis(h, "right");
h2=plot(h, x2, y2,sty,'linewidth', app.WidthEditField.Value,'tag','TiltTideE','color',lineClrs(iClr,:));
hold(h, "on");
yyaxis(h, "right");
h2=plot(h, x3, y3,sty,'linewidth', app.WidthEditField.Value,'tag','TiltTideE','color',lineClrs(iClr,:));
hold(h, "on");
xlabel(h, 'Time');
title(h, 'NE Strain Meter');
yyaxis(h, "left"); ylabel(h, 'Uncalibrated Strain (n\epsilon)');
yyaxis(h, "right"); ylabel(h, 'Tilt (nrad)');
h2 = legend(h, legendH, legendStr, 'location', 'northeast','tag', 'legendNE'); if (~app.LegendCheckBox.Value) h2.Visible = "off"; end
xlim(app.UIAxesNWTEN,"tight");
xlim(app.UIAxesBaro,"tight");

请先登录,再进行评论。

采纳的回答

Kristoffer Walker
Kristoffer Walker 2024-12-11
The solution to this is to recognize that the property of interest to make consistent across all the vertically stacked axes is the first element of the UIAxes InnerPosition properties. This refers precisely to the box of interest. Note that on this website, the 'blue box' in the figure outlining the InnerPosition is incorrectly labeled the "Position" property in the caption.
So for me, at the end of all my plot updates, I simply need to choose one of the vertically stacked axes as the reference, and then set the other's to have its InnerProperty(1) value:
app.UIAxes1.InnerPosition(1) = app.UIAxes0.InnerPosition(0);
app.UIAxes1.InnerPosition(2) = app.UIAxes0.InnerPosition(0);
etc.

更多回答(1 个)

Strider
Strider 2024-12-8
编辑:Strider 2024-12-8
Using a <https://www.mathworks.com/help/matlab/ref/tiledlayout.html tiledlayout> would do this for you without any additional position calculus.
You would only need to specify a uipanel as the parent of your tiled layout. See the example below.
Something to consider when using UI axes is that it is essientially a UIPanel and axes together (I think I read that on a mathworks answer one time). Using something like tiledlayout and regular axes is usually better performance (initial creation, and reactivity) and it can do everything a UIAxes can do.
One difference is you do have to programatically asign callbacks, unlike UIAxes that you can do in the app designer.
clearvars
% data
x1=0:.1:1;
y1=x1;
y2=100*y1;
% tiled layout
% p = some parent like a uipanel
% t = tiledlayout(p,'vertical')
t=tiledlayout('vertical');
% first axis
ax=nexttile(t);
plot(ax, x1, y1)
ylabel(ax,'Label1 left')
hold(ax,'on')
yyaxis right
plot(ax,x1,y2)
ylabel(ax,'Label1 right')
ylim(ax,[0 10]) % just to show both lines
% next axis
ax2=nexttile(t);
plot(ax2, x1, y2)
ylabel(ax2,'Label2 left')
hold(ax2,'on')
yyaxis right
plot(ax2,x1,y1)
ylabel(ax2,'Label2 right')
ylim(ax2,[0 10]) % just to show both lines
% insert push button callback to your app to add / delete axes
  9 个评论
Voss
Voss 2024-12-11
@Kristoffer Walker: The syntax "tiledlayout(parent)", i.e., not specifying the tiledlayout arrangement or dimensions, was introduced in R2024b (see the item here under R2024b), so that explains why
t = tiledlayout(app.UIFigure);
doesn't work for you under R2022b.
Similarly, specifying "vertical" or "horizontal" as the arrangement was introduced in R2023a, so those are also unavailable.
In R2022b, looks like your options are:
% use 'flow' arrangement
t = tiledlayout(app.UIFigure,'flow');
% or specify the dimensions
t = tiledlayout(app.UIFigure,3,2);
Kristoffer Walker
Kristoffer Walker 2024-12-12
Strider, I tried uipanel as well. Thanks again for all your help

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Graphics Objects 的更多信息

标签

产品


版本

R2022b

Community Treasure Hunt

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

Start Hunting!

Translated by