2014-02-04 2 views
0

Я хочу нарисовать линию с помощью мыши (в интерактивном режиме), я использовал C# и WinForm, строка должна появляться в любое время от начальной точки (когда мышь нажимает на панель) до текущее положение мыши, точно так же, как рисование линии в Paint.Рисование строки с помощью мыши в панели

но код производит много строк, я знаю, почему, но я не знаю, как преодолеть эту проблему

enter image description here

Вот мой код:

namespace WindowsFormsApplication2 
{ 
public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    Graphics g; 
    Pen myPen = new Pen(Color.Red); 
    Point p = new Point(); 
    bool flag = false; 


    private void panel1_MouseDown(object sender, MouseEventArgs e) 
    { 
     flag = true; 
     p = e.Location; 
    } 

    private void panel1_MouseMove(object sender, MouseEventArgs e) 
    { 
     if (flag) 
     { 
      g = panel1.CreateGraphics(); 
      myPen.Width = 3; 

      Point p2 = new Point(); 
      p2 = e.Location; 

      g.DrawLine(myPen, p, p2); 

     } 
    } 

    private void panel1_MouseUp(object sender, MouseEventArgs e) 
    { 
     flag = false; 
    } 

}} 

Любая помощь ? я хочу нарисовать много строк и максимально упростить код!

+0

Я мало знаю о C# рисунке, но я думаю, проблема в том, что вы не обновляете свой холст перед тем, как рисовать новую строку. – rendon

+1

Многие, многие пороки CreateGraphics(). Другой здесь, вы рисуете новую строку, но никогда не стираете старую. Вызовите Invalidate() и используйте событие Paint для рисования. –

+0

@rendon Ok проблема решена, но есть еще одна проблема, когда я рисую новую строку, предыдущая строка исчезает !! – HforHisham

ответ

1

Вам необходимо будет лучше управлять рисунком. Некоторые указатели:

  1. Не использовать CreateGraphics. Вместо этого используйте событие Paint, уже предоставленное элементом управления.
  2. Сделайте свой рисунок в собственном унаследованном классе. Не набирайте класс Form, если вы не рисуете на форме.

Вот пример класса. Он унаследован от Panel. Просто добавьте это в форму, например, в конструктор формы, используя что-то вроде this.Controls.Add(new PanelWithMouseDraw());.

Примечание: для этого используется Tuple, который, как мне кажется, требует .NET 4.0 или выше. Вы можете заменить эту структуру чем-то другим, если нужно ... вам просто нужно сохранить список пар Point.

namespace WindowsFormsApplication1 
{ 
    public class PanelWithMouseDraw : Panel 
    { 
     private Point _origin = Point.Empty; 
     private Point _terminus = Point.Empty; 
     private Boolean _draw = false; 
     private List<Tuple<Point, Point>> _lines = new List<Tuple<Point, Point>>(); 

     public PanelWithMouseDraw() 
     { 
      Dock = DockStyle.Fill; 
      DoubleBuffered = true; 
     } 

     protected override void OnMouseDown(MouseEventArgs e) 
     { 
      base.OnMouseDown(e); 
      if (e.Button == MouseButtons.Left) 
      { 
       _draw = true; 
       _origin = e.Location; 
      } 
      else 
      { 
       _draw = false; 
       _origin = Point.Empty; 
      } 

      _terminus = Point.Empty; 
      Invalidate(); 
     } 

     protected override void OnMouseUp(MouseEventArgs e) 
     { 
      base.OnMouseUp(e); 
      if (_draw && !_origin.IsEmpty && !_terminus.IsEmpty) 
       _lines.Add(new Tuple<Point, Point>(_origin, _terminus)); 
      _draw = false; 
      _origin = Point.Empty; 
      _terminus = Point.Empty; 
      Invalidate(); 
     } 

     protected override void OnMouseMove(MouseEventArgs e) 
     { 
      base.OnMouseMove(e); 
      if (e.Button == MouseButtons.Left) 
       _terminus = e.Location; 
      Invalidate(); 
     } 

     protected override void OnPaint(PaintEventArgs e) 
     { 
      foreach (var line in _lines) 
       e.Graphics.DrawLine(Pens.Blue, line.Item1, line.Item2); 
      if (!_origin.IsEmpty && !_terminus.IsEmpty) 
       e.Graphics.DrawLine(Pens.Red, _origin, _terminus); 
     } 
    } 
} 
+0

Это идеальное решение для меня. Один вопрос: как я вернусь обратно к управлению, управляемому событиями. Например: у меня есть кнопка на SuperPanel, и она должна рисовать линию так же, как у вас здесь, но только глядя на набор bool? Пример: button_click = SuperPanel1.StartDrawing (Point StartPoint), затем OtherButton_Click = SuperPanel1.StopDrawing() ?? Пожалуйста помоги! :) – MaxOvrdrv

+0

, так что вы знаете, я задал свой вопрос, связанный с вашим ответом, здесь: http://stackoverflow.com/questions/26720642/draw-line-between-point-and-cursor-location ... Заранее спасибо! – MaxOvrdrv

0

Простой исправить, изменить метод panel1_MouseMove следующим образом:

private void panel1_MouseMove(object sender, MouseEventArgs e) 
{ 
    if (flag) 
    { 
     g = panel1.CreateGraphics(); 
     myPen.Width = 3; 

     Point p2 = new Point(); 
     p2 = e.Location; 

     g.DrawLine(myPen, p, p2); 
     p = p2; // just add this 

    } 
} 

Имейте в виду, что это будет работать с любой кнопкой мыши вниз, влево или вправо не имеет значение.

Edit1:

Это должно нарисовать прямую линию и все предыдущие.

namespace WindowsFormsApplication2 
{ 
public partial class Form1 : Form 
{ 
    public struct Line 
    { 
     public Point start; 
     public Point end; 
    } 

    public Form1() 
    { 
     InitializeComponent(); 
    } 

    Pen erasePen = new Pen(Color.White, 3.0F); 
    Pen myPen = new Pen(Color.Red, 3.0F); 
    Point p = new Point(); 
    Point endPoint = new Point(); 
    bool flag = false; 
    List<WindowsFormsApplication2.Form1.Line> lines = new List<WindowsFormsApplication2.Form1.Line>(); 


    private void panel1_MouseDown(object sender, MouseEventArgs e) 
    { 
     flag = true; 
     p = e.Location; 
     endPoint = p; 
    } 

    private void panel1_MouseMove(object sender, MouseEventArgs e) 
    { 
     if (flag) 
     { 
      Graphics g = panel1.CreateGraphics(); 

      Point p2 = e.Location; 

      EraseLine(p, endPoint, g); 

      DrawAllLines(lines, g); 

      DrawLine(p, p2, g); 

      endPoint = p2; 

      g.Dispose(); 
     } 
    } 

    private void panel1_MouseUp(object sender, MouseEventArgs e) 
    { 
     // redraw for one last time... 
     Graphics g = panel1.CreateGraphics(); 

     Point p2 = e.Location; 

     lines.Add(new Line { start = p, end = p2}); 

     EraseLine(p, endPoint, g); 

     DrawAllLines(lines, g); 

     flag = false; 

     g.Dispose(); 
    } 

    private void DrawLine(Point start, Point end, Graphics g) 
    { 
     g.DrawLine(myPen, start, end); 
    } 

    private void DrawLine(WindowsFormsApplication2.Form1.Line line, Graphics g) 
    { 
     g.DrawLine(myPen, line.start, line.end); 
    } 

    private void DrawAllLines(List<WindowsFormsApplication2.Form1.Line> allLines, Graphics g) 
    { 
     foreach(WindowsFormsApplication2.Form1.Line l in allLines) 
     { 
      g.DrawLine(myPen, l.start, l.end); 
     } 
    } 

    private void EraseLine(Point start, Point end, Graphics g) 
    { 
     g.DrawLine(erasePen, start, end); 
    } 

}} 
+0

Это не приведет к прямой линии – HforHisham

+0

Получаю, я думал, вы хотите нарисовать своего рода многоугольник. – Abhinav

Смежные вопросы