简体   繁体   中英

Cancel a line drawn on a wpf canvas (C#)

I use the following code to draw line on a wpf canvas, and I'd like to be able to press a "cancel" button to erase the last line that was added.

private void Canvas_MouseDown_1(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    if (e.ButtonState == MouseButtonState.Pressed) {
        currentPoint = e.GetPosition(this);
    }
}

private void Canvas_MouseMove_1(object sender, System.Windows.Input.MouseEventArgs e) 
{
    SolidColorBrush brush = new SolidColorBrush(Colors.Red);
    if (e.LeftButton == MouseButtonState.Pressed)
    {
        Line line = new Line();

        line.Stroke = brush;
        line.StrokeThickness = 3;
        line.X1 = currentPoint.X;
        line.Y1 = currentPoint.Y;
        line.X2 = e.GetPosition(this).X;
        line.Y2 = e.GetPosition(this).Y;

        currentPoint = e.GetPosition(this);

        paintSurface.Children.Add(line);
    }
}

The way I tried to do it is by removing children from the canvas (paintSurface), which seems to be the way to go. However, when I draw a line, it is made of lots of small children lines (more like dots), and I only erase them one at a time. Here is what this partial solution looks like :

private void button5_Click(object sender, RoutedEventArgs e)
{
    if (paintSurface.Children.Count != 0)
        paintSurface.Children.RemoveAt(paintSurface.Children.Count - 1);
}

I would need to be able to get the index of the first child of every line I draw and store them, so I can erase all children after this one. Any idea ? Thanks in advance !

EDIT :

I found a way to answer my problem, but I won't mark it as the answer as it's very ugly. The best way would be, as Clemens suggested, to use Polylines (he describes how in a comment) :

On mouseDown I read the number of children on the canvas, on mouseUp I read it again to know the number of children my line created. I add this to a list, then when I press the cancel button, I delete as many children as the last element of my list and remove this element.

It works like a charm though...

The creation of all the tiny line segments is caused by the sample rate at which the mouse move is detected.

A solution might be to guess what the user intended as a single line:

  • by measuring the length of each tiny stroke
  • the angle between two neighboring lines
  • the time between the drawing of two neighboring lines

If any of these surpass a certain threshold it could be a logical break between two lines.

Note that for measuring the time between two lines you will need to store the time somewhere, whereas the first two measurements can be done on any given sequence.

Another way is to sample less often:

  • if the mouse didn't move that much, do not add a line yet unless the mouse changed direction

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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