在 WindowsForms DataVisualization Chart 中限制纵横比 [英] Constrain aspect ratio in WindowsForms DataVisualization Chart
问题描述
使用 System.Windows.Forms.DataVisualization.Charting.Chart
中的图表控件,我正在制作散点图.
如何约束它,使 X 轴的刻度与 Y 轴的刻度相同?
简单地将控件本身设置为正方形是不够的,因为它具有用于绘制和标记不相等轴的内部边距.
我可以选择一个特定的尺寸并将其调整为方形,但它需要既方形又可调整大小.
我在文档和属性浏览器中搜索了高低,但在调整大小事件中找不到任何内容或想出任何方法.
这是一个很好的问题,但不幸的是,没有像锁定两个 Axes
或设置一个值这样的简单解决方案..
让我们先看看相关的玩家:
Chart
控件有一个名为ClientSize
的内部Size
,也就是Chart.Size
减去边界.两种尺寸均以像素为单位.里面可能有一个或多个
有点挤:
然后再次正方形:
注意绿色
ChartArea
如何为Labels
和Legend
保留足够的空间,以及坐标轴的自动缩放仍然有效.但是 X 轴标签现在不适合在一行中.还要注意ChartArea.BackColor
实际上 是InnerPlotArea
的颜色!请注意,在对
ChartArea
布局进行修改(例如放大或移动或删除Legends)后,您可能需要刷新变量
或改变ipp0
以反映更改的百分比Labels
等的大小或角度.当然,您可以修改函数以传入任何其他比例以保持而不是将绘图区域保持为正方形..
Using the charting control from
System.Windows.Forms.DataVisualization.Charting.Chart
, I am making a scatter plot.How can I constrain it so that the scale of the X axis is the same as the scale of the Y axis?
Simply setting the control itself to be square is insufficient, because it has internal margins for drawing and labeling the axes which are not equal.
I could pick a specific size and tweak it to be square, but it needs to be both square and resizable.
I've searched high and low in the documentation and in the property browser, but I can't find anything or think of any ways to do it in the resize event.
解决方案This is a good question but unfortunately there is no simple solution like locking the two
Axes
or setting one value..Let's start by looking at the relevant players:
The
Chart
control has an innerSize
calledClientSize
, which is theChart.Size
minus the borders. Both sizes are measured in pixels.Inside there may be one or more
ChartAreas
. Each has aPosition
which is of typeElementPosition
.Inside each
ChartArea
the is an area which is used for the actual drawing of the points; it is calledInnerPlotPosition
.
The InnerPlotPosition property defines the rectangle within a chart area element that is used for plotting data; it excludes tick marks, axis labels, and so forth.
The coordinates used for this property (0,0 to 100,100) are related to the ChartArea object, and not to the entire Chart.
The InnerPlotPosition property can be used to align multiple chart areas. However, if one chart area has tick marks and axis labels and another one does not, their axis lines cannot be aligned.
- Both
ChartArea.Position
andChartArea.InnerPlotPosition
contain not just the location but also the size of the areas; all values are in percent of the outer area, ieChartArea.InnerPlotPosition
is relative to theChartArea.Position
andChartArea.Position
is relative to theChart.ClientSize
. All percentages go from0-100
.
So the
ChartArea
includesLabels
andLegends
as well asAxes
andTickMarks
..What we want is to find a way to make the
InnerPlotArea
square, i.e. have the same width and height in pixels. The percentages won't do!Let's start with a few simple calculations; if these are the data we have..:
// we'll work with one ChartArea only..: ChartArea ca = chart1.ChartAreas[0]; ElementPosition cap = ca.Position; ElementPosition ipp = ca.InnerPlotPosition;
.. then these are the pixel sizes of the two areas:
// chartarea pixel size: Size CaSize = new Size( (int)( cap.Width * chart1.ClientSize.Width / 100f), (int)( cap.Height * chart1.ClientSize.Height / 100f)); // InnerPlotArea pixel size: Size IppSize = new Size((int)(ipp.Width * CaSize.Width / 100f), (int)(ipp.Height * CaSize.Height / 100f));
Ideally we would like the
InnerPlotArea
to be square; since can't very well let the smaller side grow (or else the chart would overdraw,) we need to shrink the larger one. So the new pixel size of theInnerPlotArea
isint ippNewSide = Math.Min(IppSize.Width, IppSize.Height);
What next? Since the
Chart.Size
has just been set, we don't want to mess with it. Nor should we mess with theChartArea
: It still needs space to hold theLegend
etc..So we change the size of the
InnerPlotArea
..:First create a class level variable to store the original values of the
InnerPlotPosition
:ElementPosition ipp0 = null;
We will need it to keep the original percentages, i.e. the margins in order to use them when calculating the new ones. When we adapt the chart the then current ones will already have been changed/distorted..
Then we create a function to make the
InnerPlotArea
square, which wraps it all up:void makeSquare(Chart chart) { ChartArea ca = chart.ChartAreas[0]; // store the original value: if (ipp0 == null) ipp0 = ca.InnerPlotPosition; // get the current chart area : ElementPosition cap = ca.Position; // get both area sizes in pixels: Size CaSize = new Size( (int)( cap.Width * chart1.ClientSize.Width / 100f), (int)( cap.Height * chart1.ClientSize.Height / 100f)); Size IppSize = new Size((int)(ipp0.Width * CaSize.Width / 100f), (int)(ipp0.Height * CaSize.Height / 100f)); // we need to use the smaller side: int ippNewSide = Math.Min(IppSize.Width, IppSize.Height); // calculate the scaling factors float px = ipp0.Width / IppSize.Width * ippNewSide; float py = ipp0.Height / IppSize.Height * ippNewSide; // use one or the other: if (IppSize.Width < IppSize.Height) ca.InnerPlotPosition = new ElementPosition(ipp0.X, ipp0.Y, ipp0.Width, py); else ca.InnerPlotPosition = new ElementPosition(ipp0.X, ipp0.Y, px, ipp0.Height); }
You would call the function after or during resizing.
private void chart1_Resize(object sender, EventArgs e) { makeSquare(chart1); }
Here the function is at work:
The original size:
Squeezed a little:
And made square again:
Note how the green
ChartArea
reserves enough space for theLabels
and theLegend
and how the automatic scaling for the axes still works.. But the X-Axis labels now don't fit in one row. Also note how theChartArea.BackColor
actually is the color of theInnerPlotArea
only!Note that you may have to refresh the variable
ipp0
to reflect the changed percentages, after making modification to theChartArea
layout like enlarging or moving or removingLegends
or changing the size or angle ofLabels
etc..Of course you can modify the function to pass in any other ratio to keep instead of keeping the plot area a square..
这篇关于在 WindowsForms DataVisualization Chart 中限制纵横比的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!