从TextBoxes中的Chart Values获取绘图点的坐标?

在设计师中我有两个TextBoxes。 还有一个Chart控件。 我希望当我输入第一个textBox时数字120和第二个输入数字1它将在120,1中绘制图表上的点,但我的意思是120和1作为轴x和轴y值。

图表

红色圆圈不在120和1.我的意思是红色圆圈应该在120的左轴上绘制。如果我将代替120 116而不是1 25,那么应该在左轴上绘制圆圈116并在25的底部轴上。

但现在圆圈被绘制出图表。

这是我的代码:

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Windows.Forms.DataVisualization.Charting; using System.Drawing.Drawing2D; using System.Collections; namespace Test { public partial class Form1 : Form { private Point startPoint = new Point(); private Point endPoint = new Point(); private int X = 0; private int Y = 0; private List points = new List(); private Point lastPoint = Point.Empty; private ArrayList myPts = new ArrayList(); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Random rdn = new Random(); for (int i = 120; i > 0; i--) { chart1.Series["Series1"].Points.AddXY (rdn.Next(0, 10), rdn.Next(0, 10)); } chart1.Series["Series1"].ChartType = SeriesChartType.FastLine; chart1.Series["Series1"].Color = Color.Red; ChartArea area = chart1.ChartAreas[0]; area.AxisX.Minimum = 1; area.AxisX.Maximum = 30; area.AxisY.Minimum = 1; area.AxisY.Maximum = 120; LineAnnotation line = new LineAnnotation(); Point p1 = new Point(1, 120); chart1.Annotations.Add(line); line.AxisX = area.AxisX; line.AxisY = area.AxisY; line.IsSizeAlwaysRelative = false; line.X = 1; line.Y = 120; line.Right = 30; line.Bottom = 1; line.LineColor = Color.Blue; line.LineWidth = 3; } SolidBrush myBrush = new SolidBrush(Color.Red); private void chart1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; foreach (Point p in myPts) g.FillEllipse(myBrush, pX, pY, 10, 10); } private void chart1_MouseClick(object sender, MouseEventArgs e) { myPts.Add(new Point(X,Y)); chart1.Invalidate(); } private void txtT_TextChanged(object sender, EventArgs e) { X = int.Parse(txtWeight.Text); } private void txtDays_TextChanged(object sender, EventArgs e) { Y = int.Parse(txtDays.Text); } } } 

我做的是在输入两个textBoxes值后,当我用鼠标点击Chart控制区域的任何地方时,它应该在TextBoxes的坐标上绘制圆圈。

但是圈子并没有在正确的地方画画。

textBox名称txtT是左侧的左侧值。 textBox txtDays应该是底部值的轴。

将绘图坐标转换为DataPoints和返回的任务并不完全直观。

这是可能的,但你需要了解规则并支付一定的价格。

我在这篇文章中概述了方法,值得研究..

但随着问题不断出现,这里有一个更通用的解决方案。

以下是如何调用它:

 private void button11_Click(object sender, EventArgs e) { valuePoints.Add(new PointF(640, 1)); valuePoints.Add(new PointF(670, 10)); paintToCalaculate = true; chart1.Invalidate(); } 

这是结果:在值640, 1670, 10处绘制两个红点: 在此处输入图像描述

尽管我已经在图表中进行了缩放和滚动并且还调整了它的大小,但这些点被正确放置了。

为了使它工作,我们需要三个类级变量:一个标志和两个点列表。 一个列表是输入,其中图表中的值是点,另一个是输出,接收当前像素坐标。

 bool paintToCalaculate = false; List drawPoints = new List(); List valuePoints = new List(); 

我使用一个标志来避免在系统重绘时重新计算Points。 设置后,我通过使Chart Invalidating触发Paint事件。 在Paint事件期间,我重置了标志。

请注意,这些值非常不稳定 :它们会发生变化:

  • 无论何时缩放或滚动
  • 每当您调整图表大小时
  • 每当布局发生变化时,可能是因为新点需要空间或触发标签格式的更改。

因此,必须在每个此类事件上更新这些绘图坐标!

这是一个例子,它负责缩放和滚动:

 private void chart1_AxisViewChanged(object sender, ViewEventArgs e) { paintToCalaculate = true; chart1.Invalidate(); } 

您需要将这两行或一个函数添加到程序中的其他几个位置,具体取决于您允许在图表中发生的事情。 Resize也是一个明显的候选者。

现在为实际的计算。 它使用ValueToPixelPosition ,它可以完成所有工作。 不幸的是,它仅适用图表的三个绘制事件( PrePaintPaintPostPaint )中的任何一个。 在这里,我使用普通的Paint事件。

 private void chart1_Paint(object sender, PaintEventArgs e) { if (paintToCalaculate) { Series s = chart1.Series.FindByName("dummy"); if (s == null) s = chart1.Series.Add("dummy"); drawPoints.Clear(); s.Points.Clear(); foreach (PointF p in valuePoints) { s.Points.AddXY(pX, pY); DataPoint pt = s.Points[0]; double x = chart1.ChartAreas[0].AxisX.ValueToPixelPosition(pt.XValue); double y = chart1.ChartAreas[0].AxisY.ValueToPixelPosition(pt.YValues[0]); drawPoints.Add(new Point((int)x, (int)y)); s.Points.Clear(); } paintToCalaculate = false; chart1.Series.Remove(s); } //.. // now we can draw our points at the current positions: foreach (Point p in drawPoints) e.Graphics.FillEllipse(Brushes.Red, pX - 2, pY - 2, 4, 4); } 

请注意,我添加和删除了一个虚拟Series ,并为每个数据点添加并清除一个Point ,只是为了计算其像素坐标。 是的,有点牵扯,但结果是值得的..

我假设您可以更改Button_Click代码以读取TextBoxes中的值而不是使用我的硬编码数字。