c# - MS 图表矩形注释宽度以百分比而非像素为单位

标签 c# vb.net annotations mschart

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

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

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

最佳答案

恭喜您,您在文档中发现了一个错误!只需点击 Annotation.Height 的链接即可轻松发现文档..

Chart 控件中的许多其他控件一样,Annotation 的尺寸实际上以百分比给出。这样做的优点是它们可以像许多其他元素一样通过 Chart 控件巧妙地放大和缩小。

因此,如果将图表的宽度加倍,则显示的 DataPoints 的空间基本上也会加倍,并且如果您的 Annotation 超过了之前宽度的 1/3调整图表大小后仍然会这样做..

这很好。

但不是你想要的..

因此,要将大小设置为固定大小(以像素为单位),您需要执行以下操作:

  • 以百分比计算所需的大小并进行设置
  • 每次调整图表或其布局时都重复此操作

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

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

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

相反,它被计算为 ChartArea CAInnerPlotPosition 的百分比。

InnerPlotPosition 默认情况下设置为 Auto,因此可以访问其值,例如CA.InnerPlotPosition.Width 将返回 0f;但您可以通过执行以下操作获得(当前!!)值:

RectangleF IPP = CA.InnerPlotPosition.ToRectangleF();

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

RectangleF CAP = CA.Position.ToRectangleF();

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

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

因此您需要在每个Resize事件上重新计算,或者更好的是:编写一个函数来为您执行此操作,您可以在需要时调用该函数。

结果是一个注释,无论您如何调整图表的大小,它都会(几乎由于四舍五入)保持其大小..

以下是一些有用的功能:

此函数返回 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);
}

这个类似,返回 ChartArea's InnerplotPosition 的当前 ClientRectangle(以像素为单位):

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);
}

最后一个将像素大小转换为百分比大小的方法,同样仅当前有效,即直到下一次大小或布局更改为止......:

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);
}

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

enter image description here enter image description here

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

另请注意我在 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)));
}

这是调整大小事件:

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;
}

关于c# - MS 图表矩形注释宽度以百分比而非像素为单位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36491231/

相关文章:

c# - 将 SQL Server json 属性与代码优先 EF 一起使用

.net - 如何检查 Sub 是否正在处理非自定义事件?

.net - VB.Net SerialPort 读取返回碎片数据集

junit - 如何仅对具有自定义注释的测试运行junit?

java - Dagger 2 多重绑定(bind)教程的@AutoAnnotation 不起作用。如何让它发挥作用?

c# - 列出客户端打印机

c# - 通过最大化按钮调整表单大小时未触发ResizeEnd事件?

如果项目在层次结构中处于非事件状态,则触发 C# if 条件

.net - 在 LINQ 查询中获取当前枚举器(迭代器?)。就像 for 循环中的当前索引一样

java - Java 注解的工作