约束在WindowsForms DataVisualization图表宽高比约束在WindowsFo

2019-05-12 11:05发布

使用从图表控件System.Windows.Forms.DataVisualization.Charting.Chart ,我想提出一个散点图。

我怎么能限制它使得X轴的比例是相同的Y轴的规模有多大?

简单地设定控制本身是正方形是不够的,因为它具有用于绘制和标记,其是不相等的轴内部空间。

我可以选择一个特定的大小,并调整它是方形的,但它需要两个广场和调整大小。

我已经搜查高和低的文档和属性浏览器,但我无法找到任何东西,想到的任何方式来做到这一点的resize事件。

Answer 1:

这是一个很好的问题,但遗憾的是,例如把两个没有简单的解决办法Axes或设置一个值..

让我们通过查看相关的玩家开始:

  • Chart控制具有内部Size称为ClientSize ,这是Chart.Size减去边界。 两种尺寸以像素为单位。

  • 里面可能有一个或多个ChartAreas 。 每个人都有一个Position ,其是类型的ElementPosition

  • 每个内部ChartArea的是其用于点的实际的绘制的区域; 它被称为InnerPlotPosition

所述InnerPlotPosition属性定义了用于绘制数据的图表区域元件内的矩形; 它排除了刻度线,轴标签,等等。

用于此属性的(0,0 100,100)坐标都涉及到ChartArea对象,而不是整个图表。

该InnerPlotPosition属性可用于对齐多个图表区域。 然而,如果一个图表区域具有刻度标记和轴标签和另外一个没有,其轴线不能对准。

  • 无论ChartArea.PositionChartArea.InnerPlotPosition不仅包含位置 而且面积的大小 ; 所有值都在外部区域的百分比 ,即ChartArea.InnerPlotPosition是相对于ChartArea.PositionChartArea.Position是相对于Chart.ClientSize 。 所有百分比从去0-100

所以ChartArea包括LabelsLegends ,以及AxesTickMarks ..

我们要的是找到一种方法,使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储备足够的空间LabelsLegend ,以及如何为坐标轴自动比例仍然有效。但X轴的标签,现在不适合一行。 还要注意如何ChartArea.BackColor 实际上是颜色InnerPlotArea而已!

请注意,您可能需要刷新变量ipp0以反映变化的百分比,使修改后ChartArea布局像放大或移动或删除Legends或改变大小或角度Labels等。

当然,你可以修改函数中的任何其他比例来传递,而不是继续保持绘图区正方形的..



文章来源: Constrain aspect ratio in WindowsForms DataVisualization Chart