简体   繁体   English

如何用鼠标在图表控件中绘制图形

[英]How to draw a graph in chart control with mouse

My task is to draw a graph in chart control using mouse and retrieve the (X,Y) points from the Graph. 我的任务是使用鼠标在图表控件中绘制图形,并从图形中检索(X,Y)点。

I tried of drawing a graph with mouse. 我尝试用鼠标绘制图形。 Here is the normal Graph looks like. 这是正常的Graph外观。 在此处输入图片说明 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);
        }
    }

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. 现在我需要知道的是:1)我的图形不应远离图表控件的X和Y轴点。 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. 2)我需要知道相对于图表轴而不是形状轴绘制的图形的X,Y点。

I use C# VS 2010 Win-forms. 我使用C#VS 2010 Win-forms。

Chart uses a different coordinate system for its content than its Control surface, ie the mouse loacation; Chart 的内容与其控制表面使用的坐标系统不同,即鼠标的位置; there are conversion functions but they come with a caveat: They are only guaranteed to work in the Paint events.. 有转换函数,但它们带有警告:仅保证它们可以在Paint事件中使用。

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..: 你可以看到两个图形叠加非常漂亮:将DataPoints都连接在蓝线和虚线红线的像素点..:

在此处输入图片说明

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

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. 请注意,这将始终清除 DataPoints并根据像素点列表使用PixelPositionToValue方法根据当前图表布局重新创建它们。 The layout will always change when things like label sizes, other scaling, other minimum/maximum values etc change. 当标签大小,其他缩放比例,其他最小/最大值等发生变化时,布局将始终更改。

Maybe you really want to work the other way round , that is change the clicked points using the ValueToPixelPosition . 也许您真的想 ValueToPixelPosition 工作 ,那就是使用ValueToPixelPosition更改单击的点。

Here is the modified example that keeps the DataPoints and recalculates the pixel points: 下面是本变形例,保持所述DataPoints并重新计算像素点:

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

This makes a lot more sense, since the DataPoints are always bound to the chart's scaling, so they are the 'real thing'. 这使得很多更有意义,因为DataPoints总是被绑定到图表的比例,因此他们是“真实的东西”。 When you resize the Chart the DataPoints and the Graphic they make up are scaled as usual and the drawn pixel points follow perfectly: 当调整图表的DataPoints和图形,他们弥补缩放和往常一样,并选取的像素点完全遵循:

在此处输入图片说明在此处输入图片说明

(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 eg the label sizes, which enforces a layout change and the paint loop.. To fix this you should probably control the labels' formats! 另请注意,有时在新点更改时仍会发生反馈循环,例如标签大小,这会强制更改布局和绘制循环。要解决此问题,您可能应该控制标签的格式!

Also note that both conversion methods only work (correctly) in the Paint event(s), probably because only then the current layout is being settled. 还要注意,这两种转换方法仅在Paint事件中(正确)起作用,这可能是因为只有这样才能解决当前布局。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM