使用从图表控件System.Windows.Forms.DataVisualization.Charting.Chart
,我想提出一个散点图。
我怎么能限制它使得X轴的比例是相同的Y轴的规模有多大?
简单地设定控制本身是正方形是不够的,因为它具有用于绘制和标记,其是不相等的轴内部空间。
我可以选择一个特定的大小,并调整它是方形的,但它需要两个广场和调整大小。
我已经搜查高和低的文档和属性浏览器,但我无法找到任何东西,想到的任何方式来做到这一点的resize事件。
使用从图表控件System.Windows.Forms.DataVisualization.Charting.Chart
,我想提出一个散点图。
我怎么能限制它使得X轴的比例是相同的Y轴的规模有多大?
简单地设定控制本身是正方形是不够的,因为它具有用于绘制和标记,其是不相等的轴内部空间。
我可以选择一个特定的大小,并调整它是方形的,但它需要两个广场和调整大小。
我已经搜查高和低的文档和属性浏览器,但我无法找到任何东西,想到的任何方式来做到这一点的resize事件。
这是一个很好的问题,但遗憾的是,例如把两个没有简单的解决办法Axes
或设置一个值..
让我们通过查看相关的玩家开始:
该Chart
控制具有内部Size
称为ClientSize
,这是Chart.Size
减去边界。 两种尺寸以像素为单位。
里面可能有一个或多个ChartAreas
。 每个人都有一个Position
,其是类型的ElementPosition
。
每个内部ChartArea
的是其用于点的实际的绘制的区域; 它被称为InnerPlotPosition
。
所述InnerPlotPosition属性定义了用于绘制数据的图表区域元件内的矩形; 它排除了刻度线,轴标签,等等。
用于此属性的(0,0 100,100)坐标都涉及到ChartArea对象,而不是整个图表。
该InnerPlotPosition属性可用于对齐多个图表区域。 然而,如果一个图表区域具有刻度标记和轴标签和另外一个没有,其轴线不能对准。
ChartArea.Position
和ChartArea.InnerPlotPosition
不仅包含位置 而且面积的大小 ; 所有值都在外部区域的百分比 ,即ChartArea.InnerPlotPosition
是相对于ChartArea.Position
和ChartArea.Position
是相对于Chart.ClientSize
。 所有百分比从去0-100
。 所以ChartArea
包括Labels
和Legends
,以及Axes
和TickMarks
..
我们要的是找到一种方法,使InnerPlotArea
广场,即在像素相同的宽度和高度。 百分比不会做!
让我们先从一些简单的计算; 如果这些是我们拥有的数据..:
// we'll work with one ChartArea only..:
ChartArea ca = chart1.ChartAreas[0];
ElementPosition cap = ca.Position;
ElementPosition ipp = ca.InnerPlotPosition;
..然后这是两个区域的像素尺寸:
// 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));
理想情况下,我们希望InnerPlotArea
是正方形; 因为不能很好地让小边长(或者图表会透支,)我们需要收缩较大的一个。 因此,新的像素尺寸InnerPlotArea
是
int ippNewSide = Math.Min(IppSize.Width, IppSize.Height);
接下来是什么? 由于Chart.Size
刚刚成立,我们不想惹它。 也不应该老惹ChartArea
:它仍然需要空间来容纳Legend
等。
所以,我们改变大小InnerPlotArea
..:
首先,创建一个类级别的变量存储的原始值InnerPlotPosition
:
ElementPosition ipp0 = null;
我们需要它来保持原有的百分比,即利润率,从而计算新的时候使用它们。 当我们适应了当时的那些将已经被更改图表/扭曲..
然后,我们创建一个函数来使InnerPlotArea
广场,它封装了这一切:
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);
}
后或调整过程中,您会调用该函数。
private void chart1_Resize(object sender, EventArgs e)
{
makeSquare(chart1);
}
这里的功能在起作用:
原稿尺寸:
挤了一点:
并提出方再次:
注意如何绿色ChartArea
储备足够的空间Labels
和Legend
,以及如何为坐标轴自动比例仍然有效。但X轴的标签,现在不适合一行。 还要注意如何ChartArea.BackColor
实际上是颜色InnerPlotArea
而已!
请注意,您可能需要刷新变量ipp0
以反映变化的百分比,使修改后ChartArea
布局像放大或移动或删除Legends
或改变大小或角度Labels
等。
当然,你可以修改函数中的任何其他比例来传递,而不是继续保持绘图区正方形的..