如何用鼠标在图表控件中绘制图形 [英] How to draw a graph in chart control with mouse

查看:15
本文介绍了如何用鼠标在图表控件中绘制图形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的任务是使用鼠标在图表控件中绘制图形并从图形中检索 (X,Y) 点.

My task is to draw a graph in chart control using mouse and retrieve the (X,Y) points from the Graph.

我尝试用鼠标绘制图形.这是正常的 Graph 样子.用鼠标绘制后,它看起来像: 我用来绘制图形的代码是:

I tried of drawing a graph with mouse. Here is the normal Graph looks like. After drawing with mouse, it looks like : The code which i used to draw graph is :

    private void Form1_Load(object sender, EventArgs e)
    {
    chart1.ChartAreas[0].AxisX.Minimum =0170101;
    chart1.ChartAreas[0].AxisX.Maximum =0175951;
    chart1.ChartAreas[0].AxisY.Minimum=0780101;
    chart1.ChartAreas[0].AxisY.Maximum=0785951;
    double range = chart1.ChartAreas[0].AxisX.Maximum - chart1.ChartAreas[0].AxisX.Minimum;
        chart1.ChartAreas[0].AxisX.Interval = range / 5;

        range = chart1.ChartAreas[0].AxisY.Maximum - chart1.ChartAreas[0].AxisY.Minimum;
        chart1.ChartAreas[0].AxisY.Interval = range / 5;
    }
    private void chart1_MouseMove(object sender, MouseEventArgs e)
    {
        if (!(FirstPoint == null))
        {
            Graphics g = chart1.CreateGraphics();
            Pen ErasePen = new Pen(Color.Transparent);
            g.DrawLine(ErasePen, FirstPoint, TempPoint);
            TempPoint = new Point(e.X, e.Y);
            this.Refresh();
        }
    }
    private void chart1_MouseDown_1(object sender, MouseEventArgs e)
    {
        FirstPoint = new Point(e.X, e.Y);
        TempPoint = new Point(e.X, e.Y);
    }

    private void chart1_MouseUp_1(object sender, MouseEventArgs e)
    {
        LineEndPoints Line = new LineEndPoints
        {
            StartPoint = FirstPoint,
            endPont = new Point(e.X, e.Y)
        };
        LinesList.Add(Line);
        // FirstPoint = null;
        this.Refresh();
    }

    private void chart1_Paint_1(object sender, PaintEventArgs e)
    {
        foreach (LineEndPoints line in LinesList)
        {
            e.Graphics.DrawLine(Pens.Green, line.StartPoint, line.endPont);
        }
        if (!(FirstPoint == null))
        {
            e.Graphics.DrawLine(Pens.Red, FirstPoint, TempPoint);
        }
    }

当我过去绘制图形时,它正在远离图表控件的最大值和最小值.现在我需要知道的是:1) 我的图形不应远离图表控件的 X 和 Y 轴点.2) 我需要知道相对于图表轴而不是表单轴绘制的图形的 X、Y 点.

When I used to draw a graph it is moving away from the max and min values of the chart control. Now what I need to know is: 1) My graph should not move away from the X and Y axis points of the chart control. 2) I need to know the X,Y points of the graph which is drawn with respect to chart axis but not with form axis.

我使用 C# VS 2010 Win-forms.

I use C# VS 2010 Win-forms.

推荐答案

Chart 使用不同的 其内容的坐标系比其控制面,即鼠标位置;有转换函数,但它们有一个警告:它们只能保证在 Paint 事件中工作..

Chart uses a different coordinate system for its content than its Control surface, ie the mouse loacation; there are conversion functions but they come with a caveat: They are only guaranteed to work in the Paint events..

ValueToPixelPosition

这是一个将像素点转换为图表点值的示例.您可以看到两个图形重叠得非常好:DataPoints 用蓝线连接,像素点用红色虚线连接..:

Here is an example that translates the pixel points to chart point values. You can see the two graphics overlaying very nicely: The DataPoints are connected in blue lines and the pixel points by dotted red lines..:

    public Form1()
    {
        InitializeComponent();
        chart1.Series[0].ChartType = SeriesChartType.Line;
        chart1.ChartAreas[0].AxisX.Minimum = 0;
        chart1.ChartAreas[0].AxisX.Maximum = 500;
        chart1.ChartAreas[0].AxisY.Minimum = 0;
        chart1.ChartAreas[0].AxisY.Maximum = 500;
    }

    List<Point> points = new List<Point>();

    private void chart1_MouseClick(object sender, MouseEventArgs e)
    {
        points.Add(e.Location);
        chart1.Invalidate();
    }

    private void chart1_Paint(object sender, PaintEventArgs e)
    {
        chart1.Series[0].Points.Clear();
        foreach(Point pt in points)
        {
            double dx = chart1.ChartAreas[0].AxisX.PixelPositionToValue(pt.X);
            double dy = chart1.ChartAreas[0].AxisY.PixelPositionToValue(pt.Y);
            chart1.Series[0].Points.AddXY(dx, dy);
        }
        if (points.Count > 1)
            using (Pen pen = new Pen(Color.Red, 2.5f))
               e.Graphics.DrawLines(pen, points.ToArray());
    }

请注意,这将始终清除 DataPoints 并从像素点列表中重新创建它们,根据使用 PixelPositionToValue 的当前图表布局方法.当标签大小、其他缩放比例、其他最小值/最大值等更改时,布局将始终更改.

Note that this will always clear the DataPoints and recreate them from the pixel points list, according to the current chart layout using the PixelPositionToValue method. The layout will always change when things like label sizes, other scaling, other minimum/maximum values etc change.

也许您真的想反过来工作,即使用 ValueToPixelPosition 更改点击点.

Maybe you really want to work the other way round, that is change the clicked points using the ValueToPixelPosition.

这是保留DataPoints并重新计算像素点的修改示例:

Here is the modified example that keeps the DataPoints and recalculates the pixel points:

    List<Point> points = new List<Point>();
    Point lastPoint = Point.Empty;

    private void chart1_MouseClick(object sender, MouseEventArgs e)
    {
        lastPoint = e.Location;
        chart1.Invalidate();
    }

    private void chart1_Paint(object sender, PaintEventArgs e)
    {
        // if we have a new point, convert to DataPoint and add to Series.Points:
        if (lastPoint != Point.Empty)
        {
            double dx = chart1.ChartAreas[0].AxisX.PixelPositionToValue(lastPoint.X);
            double dy = chart1.ChartAreas[0].AxisY.PixelPositionToValue(lastPoint.Y);
            chart1.Series[0].Points.AddXY(dx, dy);
        }
        lastPoint = Point.Empty;
        // now recalculate all pixel points:
        points.Clear();
        foreach (DataPoint pt in chart1.Series[0].Points)
        {
            double x = chart1.ChartAreas[0].AxisX.ValueToPixelPosition(pt.XValue);
            double y = chart1.ChartAreas[0].AxisY.ValueToPixelPosition(pt.YValues[0]);
            points.Add(new Point((int)x, (int)y));
        }

        if (points.Count > 1)
            using (Pen pen = new Pen(Color.Red, 2.5f))
            {
                pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
                e.Graphics.DrawLines(pen, points.ToArray());
            }
    }

这更有意义,因为 DataPoints 总是绑定到图表的缩放比例,所以它们是真实的东西".当您调整图表大小时,DataPoints 和它们组成的图形会像往常一样缩放,并且绘制的像素点完美地跟随:

This makes a lot more sense, since the DataPoints are always bound to the chart's scaling, so they are the 'real thing'. When you resize the Chart the DataPoints and the Graphic they make up are scaled as usual and the drawn pixel points follow perfectly:

(当您调整第一个版本的大小时,您可以看到没有任何内容被放大或缩小,只有图表的网格线发生变化..)

(When you resize the first version you can see how nothing is being scaled up or down and only the chart's grid lines change..)

请注意,我首先设置了一些内容,因此并非我添加的每个点都会强制执行过多的布局更改.另请注意,有时当新点发生变化时仍会发生反馈循环,例如标签大小,这会强制更改布局和绘制循环.要解决此问题,您可能应该控制标签的格式!

Note that I set up a few things to start with, so that not every point I add enforces too many layout changes. Also note that sometimes there still occurs a feedback loop when the new points change e.g. the label sizes, which enforces a layout change and the paint loop.. To fix this you should probably control the labels' formats!

另请注意,这两种转换方法都只能(正确)在 Paint 事件中工作,可能是因为只有在那时才会确定当前布局.

Also note that both conversion methods only work (correctly) in the Paint event(s), probably because only then the current layout is being settled.

这篇关于如何用鼠标在图表控件中绘制图形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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