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

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

问题描述

在设计我有两个文本框。 也是一个图表控件。 我想,当我输入第一个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.

这是我的code:

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

我所做的是,在我进入这两个文本框的值,然后当我点击鼠标图表控制区域的任何地方应该绘制circule从文本框的坐标。

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.

文本框名txtT是左一个在左边的值的轴。 文本框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.

推荐答案

翻译图纸的任务坐标转换为数据点,后是不完全直观。

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.

我所概述的方式<一个href="http://stackoverflow.com/questions/29902288/how-to-draw-a-graph-in-chart-control-with-mouse">in这篇文章,这是值得研究的。

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

我用一个标志,以避免重新计算分数时,系统会引发重绘。并设置它后,我触发油漆事件由无效。在油漆事件重置标志。

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.

请注意,这些值是非常挥发性:他们改变:

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

  • 当你放大或滚动
  • 当调整图表
  • 每当布局的变化,也许是因为新的点需要的房间或触发标签格式的更改。

因此​​,那些绘制坐标将必须的更新在每个这样的事件!

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 ,油漆<$ C C $> PostPaint )。在这里,我用的是正常的油漆事件。

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

请注意,我添加和删除虚拟系列并添加和明确的一个来它为每个数据点,只计算其像素坐标。是的,有点麻烦,但结果是值得的。

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 code,从你的文本框读取值而不是在用我的硬codeD数字。

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天全站免登陆