从文本框中的图表值获取绘图点的坐标? [英] Get coordinates of a drawing point from Chart Values in TextBoxes?

查看:378
本文介绍了从文本框中的图表值获取绘图点的坐标?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In the designer I have two TextBoxes. And also a Chart control. I want that when I type in the first textBox the number 120 and in the second one type the number 1 it will draw a point on the chart in 120,1 but I mean 120 and 1 as axis x and axis y values.

红色圆圈不是在120和1.
我的意思是红色圆圈应该绘制在左轴上的120.
如果我将改为120 116而是1 25,则圆圈应绘制在左轴116和底轴25上。

The red filled circle is not at 120 and 1. I mean that the red circle should be drawn on the left axis on 120. And if I will put instead 120 116 and instead 1 25 then the circle should be drawn at the left axis 116 and on the bottom axis on 25.

但现在圆圈是从图表中绘制出来的。

But now the circle is drawn out of the chart.

这是我的代码:

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<Point> points = new List<Point>();
        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, p.X, p.Y, 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值,然后当我用鼠标点击图表控件区域的任何地方,它应该从TextBoxes的坐标绘制圆形。

What I did is that after I enter both textBoxes values then when I click anywhere on the Chart control area with the mouse it should draw the circule on the coordinates from the TextBoxes.

但是圆圈不是绘制在正确的位置。

But the circle is not drawing on the right place.

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

The textBox name txtT is the left one the axis on the left values. The textBox txtDays should is the axis on the bottom values.

推荐答案

将绘图坐标转换为DataPoints

The task of translating drawing coordinates into DataPoints and back is not exactly intuitive.

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

It is possible but you need to know the rules and pay a certain price.

我已简要介绍了此帖中的方法<

I have outlined the way in this post and it is worth looking into..

但是由于问题反复出现,这里是一个更通用的解决方案。

But as the problem is coming up repeatedly, here is a more general solution.

下面是如何调用它:

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,1 670,10

And here is the result: Two red points drawn at the values 640, 1 and 670, 10:

这些点被放置正确的事件,虽然我已经放大和滚动图表,也调整了它的大小。

The points are placed correctly event though I have zoomed and scrolled in the chart and also resized it..

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

To make it work we need three class level variables: A flag and two point lists. One list is the input with the values in the chart where the points are, the other is the output, receiving the current pixel coordinates.

bool paintToCalaculate = false;
List<Point> drawPoints = new List<Point>();
List<PointF> valuePoints = new List<PointF>();

我使用标志来避免在系统引起重画时重新计算积分。设置完成后,我通过触发 Paint 事件 c>。在 Paint 事件期间,我重置了标志。

I use a flag to avoid recalculating the Points when the system causes redraws. And after setting it I trigger the Paint event by Invalidating the Chart. During the Paint event I reset the flag.

请注意,这些值非常 strong>:他们改变:

Please note that these values are very volatile: They change:


  • 每当缩放或滚动

  • / li>
  • 每当布局发生变化时,或许是因为新点需要空间或触发标签格式的更改。

因此,这些绘图坐标必须更新

Therefore those drawing coordinates will have to be updated on each such event!

这里有一个例子,和滚动:

Here is one example, that takes care of zoom and scrolling:

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

您需要添加这两行或一个函数你的程序中的几个其他点,取决于你允许在图表中发生什么。调整大小也是一个明显的候选人。

You need to add these two lines, or a function to wrap them, to a few other spots in your program, depending what things you allow to happen in the chart.. Resize is also an obvious candidate..

现在为实际计算。它使用 ValueToPixelPosition ,这完成所有的工作。不幸的是,只有内部的图表的三个绘制事件中的任何一个( PrePaint Paint PostPaint )。这里我使用正常的 Paint 事件。

Now for the actual caculation. It is using the ValueToPixelPosition, which does all the work. Unfortunately is only works inside of any of the three paint events of a chart (PrePaint,Paint and PostPaint) . Here I use the normal Paint event.

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(p.X, p.Y);
            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, p.X - 2, p.Y - 2, 4, 4);
}

注意,我添加和删除一个虚拟 / code>,并为每个数据点添加并清除一个,以计算其像素坐标。是的,有点涉及,但结果是值得的。

Note that I add and remove a dummy Series and add and clear one Point to it for each data point, just to calculate its pixel coordinates. Yes, a bit involved, but the results are worth it..

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

I assume you can change the Button_Click code to read in the values from your TextBoxes instead of the using my hard-coded numbers..

这篇关于从文本框中的图表值获取绘图点的坐标?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆