MS Chart 矩形注释宽度百分比而不是像素

MS Chart Rectangular Annotation width in percent and not pixel

为什么 MS 图表矩形注释宽度是百分比而不是 msdn 所说的像素? https://msdn.microsoft.com/en-us/library/system.windows.forms.datavisualization.charting.annotation.width(v=vs.110).aspx

msdn 是这么说的 获取或设置注释的宽度(以像素为单位)。

我想将我的宽度设置为它声明的像素。我在这里错过了什么吗?

是的,我们不能将其设置为 % 或 px,因为 属性 值设置为双倍。 其次,pixle = H乘以W。但你只是设置图表的宽度,那你怎么能设置成pixle呢?根本不可能。我希望你能明白我的意思。

恭喜,您在文档中发现了一个错误!只需按照 link 到 Annotation.Height 文档即可轻松发现..

Annotation 的维度与 Chart 控件中的许多其他维度一样,确实以百分比给出。这样做的好处是它们可以像许多其他元素一样通过 Chart 控件巧妙地增长和收缩。

因此,如果您将图表的宽度加倍,则基本上是显示的 DataPoints 的 space 加倍,如果您的 Annotation 超过了它之前宽度的 1/3调整图表大小时仍会执行此操作..

这很好。

但不是你想要的..

因此,要将尺寸设置为以像素为单位的固定尺寸,您需要这样做:

  • 以百分比计算你想要的大小并设置它
  • 每当您调整图表大小时或其布局时重复

真正的问题是计算:如果您查看 Chart.ClientSize,您会得到以像素为单位的大小,要获得 n 个像素,您需要执行以下操作:

float WidthInPercent = 100f * n / Chart.ClientSize.width;

然而,这并没有考虑到您的 Chart 可能具有的各种元素: AnnotationSize 确实 而不是 计算为图表大小的直接百分比

而是计算为 InnerPlotPositionChartArea CA 的百分比。

InnerPlotPosition 默认设置为 Auto 所以访问它的值,例如CA.InnerPlotPosition.Width 将 return 0f;但是你可以通过这样做得到(当前!!)值:

RectangleF IPP = CA.InnerPlotPosition.ToRectangleF();

ChartArea 本身的 Size/Position 也是如此:

RectangleF CAP = CA.Position.ToRectangleF();

现在您可以将这些百分比与 (current!) Chart.ClientSize 结合起来,找出达到特定像素大小所需的百分比..

请注意,在调整 大小时,这些值会 发生变化,因为 LegendAxis 以及 Labels 等外部额外内容不会调整大小,因此它们的相对大小将相对于它们包含的元素增大或缩小..

所以你需要在每个Resize事件上重新计算,或者,更好的是:写一个函数来为你做,你可以在需要的时候调用..

结果是一个 Annotation,无论您如何调整 Chart..

的大小,它(由于四舍五入,基本上)都会保持其大小

以下是一些有用的函数:

这个return是一个ChartArea当前ClientRectangle像素

RectangleF ChartAreaClientRectangle(Chart chart, ChartArea CA)
{
    RectangleF CAR = CA.Position.ToRectangleF();
    float pw = chart.ClientSize.Width / 100f;
    float ph = chart.ClientSize.Height / 100f;
    return new RectangleF(pw * CAR.X, ph * CAR.Y, pw * CAR.Width, ph * CAR.Height);
}

这个是相似的,returns 当前 ClientRectangleChartArea's InnerplotPosition 以像素为单位:

RectangleF InnerPlotPositionClientRectangle(Chart chart, ChartArea CA)
{
    RectangleF IPP = CA.InnerPlotPosition.ToRectangleF();
    RectangleF CArp = ChartAreaClientRectangle(chart, CA);

    float pw = CArp.Width / 100f;
    float ph = CArp.Height / 100f;

    return new RectangleF(CArp.X + pw * IPP.X, CArp.Y + ph * IPP.Y, 
                            pw * IPP.Width, ph * IPP.Height);
}

最后一个将以像素为单位的大小转换为以百分比为单位的大小,再次仅在当前有效,即直到下一次更改大小或布局..:[=​​52=]

SizeF Pixels2Percent( ChartArea CA, int w, int h)
{
    RectangleF IPPR = InnerPlotPositionClientRectangle(chart1, CA);

    float pw = 100f * w / IPPR.Width ;
    float ph = 100f * h / IPPR.Height ;

    return new SizeF(pw, ph);
}

让我们看看调整大小前后的结果:

如您所见,大小保持不变。

另请注意我在 Paint 事件中绘制的彩色矩形以演示新功能!

这是 Paint 事件:

private void chart1_Paint(object sender, PaintEventArgs e)
{
    ChartArea CA = chart1.ChartAreas[0];
    e.Graphics.DrawRectangle(Pens.Violet, 
               Rectangle.Round(ChartAreaClientRectangle(chart1, CA)));
    e.Graphics.DrawRectangle(Pens.LimeGreen, 
               Rectangle.Round(InnerPlotPositionClientRectangle(chart1, CA)));
}

这是 Resize 事件:

private void chart1_Resize(object sender, EventArgs e)
{
    sizeAnn(ra, new Size(24, 36));
}

这里是尺寸函数:

void sizeAnn(RectangleAnnotation ra, Size sz)
{
    ChartArea CA = chart1.ChartAreas[0];
    SizeF pixelPercent = Pixels2Percent(CA, sz.Width, sz.Height);
    ra.Width = pixelPercent.Width;
    ra.Height = pixelPercent.Height;
}

我知道 OP 想要以像素为单位设置宽度,但如果有些人(比如我)不想以像素或百分比为单位设置宽度,而是根据实际值设置,只需设置 :

annotation.IsSizeAlwaysRelative = False
annotation.Width = whatEverValue