C#在点击测试中添加圈子

时间:2018-10-11 14:27:30

标签: c# winforms

我在Windows表单图形上有一个有效的鼠标单击事件,现在我想在每次单击上添加数据点,以使其在图形上的单击位置可见。在第3次点击时,前2次将清除,而第3次和第4次点击将具有自己的新数据点,依此类推(一次显示2个数据点以显示开始和停止位置,并且计算之间的差/差那些位置。

我当前的代码如下:

private void chart1_MouseClick(object sender, MouseEventArgs e)
{
    HitTestResult result = chart1.HitTest(e.X, e.Y);

    if (result.PointIndex >= 0)
    {
        if (diffCounter == 0)
        {
            xOne = result.Series.Points[result.PointIndex].YValues[0];
            diffCounter++;
            //Console.WriteLine("VALY " + xOne);
        }
        else if (diffCounter == 1)
        {
            xTwo = result.Series.Points[result.PointIndex].YValues[0];
            diffCounter = 0;
            //Console.WriteLine("Delta = " + Math.Round(Math.Abs(xTwo - xOne)), 2);
            pointDifferenceTextBox.Text = Math.Round((Math.Abs(xTwo - xOne)), 2).ToString();
        }
    }
}

根据在折线图(或与此相关的任何图表)上执行点击测试的位置,我找不到任何有关添加数据点的信息。

差异Counter只是int,用于确定是第一次还是第二次点击。

xOne用于获取第一个点击的y值,xTwo是获取第二个点击的y值。

编辑:我想根据执行点击测试的位置创建一个圆形数据点。

2 个答案:

答案 0 :(得分:0)

原始帖子要求在点击的位置添加DataPoint。为此HitTest没有用。

相反,您需要axis functions其中之一; PixelPositionToValue会将像素位置转换为轴 ..:

Axis ax = chart1.ChartAreas[0].AxisX;
Axis ay = chart1.ChartAreas[0].AxisY;

double x = ax.PixelPositionToValue(e.X);
double y = ay.PixelPositionToValue(e.Y);

DataPoint dp = new DataPoint(x, y);
dp.Color = Color.Red;
chart1.Series[0].Points.Add(dp);

请注意,这些功能仅在绘画之一或鼠标事件之一中仅有效

答案 1 :(得分:0)

由于帖子已更改,因此似乎有必要提供新答案。

这里是如何在Paint事件中创建两个要绘制的点。

首先我们需要存储它们:

PointF p1 = PointNull;
PointF p2 = PointNull;

要标记状态,我们还使用静态值:

static PointF PointNull = new PointF(-123f, -123f);

您也可以使用其他标志来控制第一点和第二点之间的切换。

接下来,我们需要在click中存储值:

private void chart1_MouseClick(object sender, MouseEventArgs e)
{

    Axis ax = chart1.ChartAreas[0].AxisX;
    Axis ay = chart1.ChartAreas[0].AxisY;

    double x = ax.PixelPositionToValue(e.X);
    double y = ay.PixelPositionToValue(e.Y);

    y = GetMedianYValue(chart1.Series[0], x);

    if (p1 == PointNull ||(p1 != PointNull && p2 != PointNull))
    {
        p1 = new PointF((float)x, (float)y);
        p2 = PointNull;
    }
    else
    {
        p2 = new PointF((float)x, (float)y);
    }
    // values have changed, trigger drawing them!
    chart1.Invalidate();
}

请注意,我首先使用轴功能来获取单击位置的轴值。然后,我用一个计算直线上点的函数覆盖y值。

double GetMedianYValue(Series s,  double xval )
{
    // Findclosest datapoints:
    DataPoint dp1 =  s.Points.Where(x => x.XValue <= xval).LastOrDefault();
    DataPoint dp2 =  s.Points.Where(x => x.XValue >= xval).FirstOrDefault();

    // optional
    dp1.MarkerStyle = MarkerStyle.Circle;
    dp1.MarkerColor = Color.Purple;
    dp2.MarkerStyle = MarkerStyle.Circle;
    dp2.MarkerColor = Color.Violet;

    double dx = dp2.XValue - dp1.XValue;
    double dy = dp2.YValues[0] - dp1.YValues[0];
    // same point
    if (dx == 0) return dp1.YValues[0];
    // calculate median
    double d = dp1.YValues[0] + dy / dx * ( xval - dp1.XValue) ;
    return d;
}

请注意,此功能标记仅用于测试的相邻数据点!

最后我们需要画两点:

private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
    Axis ax = chart1.ChartAreas[0].AxisX;
    Axis ay = chart1.ChartAreas[0].AxisY;

    int x1 = (int)ax.ValueToPixelPosition(p1.X);
    int y1 = (int)ay.ValueToPixelPosition(p1.Y);
    int x2 = (int)ax.ValueToPixelPosition(p2.X);
    int y2 = (int)ay.ValueToPixelPosition(p2.Y);

    if (x1 >= 0 && x1 < chart1.Width)  // sanity check
        if (p1 != PointNull)
            e.ChartGraphics.Graphics.DrawEllipse(Pens.LightSeaGreen, x1 - 3, y1 - 3, 6, 6);

    if (x2 >= 0 && x2 < chart1.Width)  // sanity check
        if (p2 != PointNull)
            e.ChartGraphics.Graphics.DrawEllipse(Pens.Red, x2 - 3, y2 - 3, 6, 6);
}

这是结果:

enter image description here