在约束WindowsForms数据可视化图表宽高比 [英] Constrain aspect ratio in WindowsForms DataVisualization Chart
问题描述
从使用 System.Windows.Forms.DataVisualization.Charting.Chart
的图表控件,我想提出一个散点图。
我怎么能限制它使X轴的比例是相同的Y轴的规模有多大?
简单的设置控制本身是方是不够的,因为它具有绘制和标签这是不相等的轴的内部空间。
我可以选择一个特定的大小,并调整它是正方形的,但它需要两个广场和调整大小。
我已经搜查高和低的文档中,并在属性浏览器,但我无法找到任何东西,或想到的什么方法可以做到这一点的resize事件。
这是一个很好的问题,但遗憾的是像锁定没有简单的解决方案两个轴
或设定一个值。
让我们通过查看相关的玩家开始:
-
的
图
控制的内尺寸
名为ClientSize
,这是Chart.Size
减去边界。这两种尺寸以像素为单位。 -
里面可能有一个或一个以上的
ChartAreas
。每个人都有一个位置
这是一个类型的ElementPosition
。 -
在每个
ChartArea
的是用于点的实际绘制的区域;它被称为的InnerPlotPosition
。
的InnerPlotPosition属性定义图表
区元素中的矩形用于绘制数据;它排除刻度标记,
轴标签,等等。
用于此属性(0,0至100,100)的坐标有关
将ChartArea对象,而不是对整个图表
的InnerPlotPosition属性可用于对齐多个图表
区。但是,如果一个图表地区的刻度线和轴标签和
另一个没有,他们的轴线不能对齐。
块引用>
- 双方
ChartArea.Position
和ChartArea.InnerPlotPosition
不仅包含在位置,但同时在尺寸的领域;所有值都在%的外区,即ChartArea.InnerPlotPosition
是相对于ChartArea.Position $的
C $ C>和ChartArea.Position
是相对于Chart.ClientSize
。所有百分比从根本0-100
。
所以
ChartArea
包括标签
和传说
以及轴
和刻度线
..
我们需要的是找到一种方法,使
InnerPlotArea
平方,即具有相同的宽度和高度的像素即可。 !百分比不会做
让我们先从一些简单的计算;如果这些是我们拥有的数据..:
//我们只有一个ChartArea工作..:
ChartArea CA = chart1.ChartAreas [0];
ElementPosition上限= ca.Position;
ElementPosition IPP = ca.InnerPlotPosition;
..然后这是两个区域的像素大小:
// chartarea像素尺寸:
规格= CASIZE新的大小((INT)(cap.Width * chart1.ClientSize.Width / 100F),
(INT)(cap.Height * chart1.ClientSize.Height / 100F));
// InnerPlotArea像素尺寸:
规格= IppSize新的大小((INT)(ipp.Width * CaSize.Width / 100F),
(INT)(ipp.Height * CaSize.Height / 100F));
在理想情况下,我们希望
InnerPlotArea
是广场;因为不能很好地让小边长(或者图表会透支,)我们需要收缩较大的一个。因此,InnerPlotArea
是
INT ippNewSide =数学的新的像素大小.Min(IppSize.Width,IppSize.Height);
下一步是什么?因为
Chart.Size
刚刚成立,我们不想惹它。也不应我们乱用ChartArea
:它仍然需要空间来容纳联想
等
所以我们修改
InnerPlotArea
..大小:
第一创建一个类级别变量存储
InnerPlotPosition
的原始值:ElementPosition ipp0 = NULL;
我们将需要它保持原有的百分比,即利润率为了计算何时使用它们新的。当我们适应了当时最新的将已经被改变了图/扭曲。
然后,我们创建一个函数,使
InnerPlotArea
平方,这都结束了:无效makeSquare(图图)
{
ChartArea CA = chart.ChartAreas [0];
//存储原始价值:
如果(ipp0 == NULL)ipp0 = ca.InnerPlotPosition;
//获得当前图表区:
ElementPosition上限= ca.Position;
//以像素为单位同时获得区域大小:
规格= CASIZE新的大小((INT)(cap.Width * chart1.ClientSize.Width / 100F),
(INT )(cap.Height * chart1.ClientSize.Height / 100F));
规格= IppSize新的大小((INT)(ipp0.Width * CaSize.Width / 100F),
(INT)(ipp0.Height * CaSize.Height / 100F));
//我们需要用更小的一面:
INT ippNewSide = Math.Min(IppSize.Width,IppSize.Height);
//计算比例因子
浮动PX = ipp0.Width / IppSize.Width * ippNewSide;
浮动PY = ipp0.Height / IppSize.Height * ippNewSide;
//使用一个或另一个:
如果(IppSize.Width< IppSize.Height)
ca.InnerPlotPosition =新ElementPosition(ipp0.X,ipp0.Y, ipp0.Width,PY);
,否则
ca.InnerPlotPosition =新ElementPosition(ipp0.X,ipp0.Y,PX,ipp0.Height);
}
后或调整过程中你会调用该函数。
私人无效chart1_Resize(对象发件人,EventArgs五)
{
makeSquare(chart1);
}
下面的功能在起作用:
注意绿色
ChartArea
如何保留对标签
足够的空间和联想
,以及如何为坐标轴自动调整功能仍然有效。但X轴的标签,现在不适合一行。还要注意如何使用ChartArea.BackColor
实际是唯一的InnerPlotArea
颜色<! / p>
请注意,您可能需要刷新变量
ipp0
来反映变化的百分比,使得修改的<$之后C $ C> ChartArea 布局就像放大或移动或删除传说
或改变标签的大小和角度
等
当然,你可以修改函数中的任何其他比例通过维持,而不是保持绘图区的方..
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数据可视化图表宽高比的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!