Как правильно нарисовать линию с помощью мыши на C#

Это мой код рисования, чтобы нарисовать линию с помощью мыши на диаграмму. Не могли бы вы помочь мне сделать это правильно ?

namespace Grafi
    {
        public partial class Form1 : Form
        {

            bool isDrawing = false;
            Point prevPoint;

            public Form1()
            {
                InitializeComponent();
            }

            private void chartTemperature_MouseDown(object sender, MouseEventArgs e)
            {
                isDrawing = true;
                prevPoint = e.Location;
            }

            private void chartTemperature_MouseMove(object sender, MouseEventArgs e)
            {
                Pen p = new Pen(Color.Red, 2); 
                if (isDrawing)
                {
                    Graphics g = chartTemperature.CreateGraphics();    
                    g.DrawLine(p, prevPoint, e.Location);
                    prevPoint = e.Location;

                    numOfMouseEvents = 0;              
                }
                p.Dispose();
            }

            private void chartTemperature_MouseUp(object sender, MouseEventArgs e)
            {
                isDrawing = false;
            }
        }
    }

проблема заключается в том, что когда я изменить размер моей disappers линии. Это disappers всякий раз, когда событие метода onpaint вызывается.

4 ответов


попробуйте это... Это метод рисования штрихов, реализованный очень просто и как можно ближе к вашему собственному коду. Stokes-это отдельные коллекции движений мыши. Каждое движение мыши между вниз и вверх записывается как Штрих, все штрихи собираются, а затем перерисовываются всякий раз, когда запускается событие paint. Этот пример прост, но может быть хорошей отправной точкой.

обратите внимание, что вам нужно будет добавить обработчик краски для диаграммы объект.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace Grafi
{
    public partial class Form1 : Form
    {
        bool isDrawing;
        // our collection of strokes for drawing
        List<List<Point>> _strokes = new List<List<Point>>();
        // the current stroke being drawn
        List<Point> _currStroke;
        // our pen
        Pen _pen = new Pen(Color.Red, 2); 

        public Form1()
        {
            InitializeComponent();
        }

        private void chartTemperature_MouseDown(object sender, MouseEventArgs e)
        {
            isDrawing = true;
            // mouse is down, starting new stroke
            _currStroke = new List<Point>();
            // add the initial point to the new stroke
            _currStroke.Add(e.Location);
            // add the new stroke collection to our strokes collection
            _strokes.Add(_currStroke);
        }

        private void chartTemperature_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDrawing)
            {
                // record stroke point if we're in drawing mode
                _currStroke.Add(e.Location);
                Refresh(); // refresh the drawing to see the latest section
            }
        }

        private void chartTemperature_MouseUp(object sender, MouseEventArgs e)
        {
            isDrawing = false;
        }

        private void chartTemperature_Paint(object sender, PaintEventArgs e)
        {
            // now handle and redraw our strokes on the paint event
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            foreach (List<Point> stroke in _strokes.Where(x => x.Count > 1))
                e.Graphics.DrawLines(_pen, stroke.ToArray());
        }
    }
}

у вас есть какие-либо проблемы с вашей текущей реализации? Работает ли это, или вы просто хотите сделать код лучше для уже работающей функции.

Я думаю, что вы логика выглядит просто отлично. Тем не менее, я бы добавил предложение using в перо следующим образом:

private void chartTemperature_MouseMove(object sender, MouseEventArgs e)
{
  using( Pen p = new Pen(Color.Red, 2)){
    if (isDrawing)
    {
      Graphics g = chartTemperature.CreateGraphics();    
      g.DrawLine(p, prevPoint, e.Location);
      prevPoint = e.Location;

      numOfMouseEvents = 0;              
    }
  }
}

таким образом, ваше перо будет размещено даже в случае каких-либо исключений, возникающих после его создания и вашего вызова Dispose.

однако вы также можете подумать о создании Pen класс переменная, поэтому вам не нужно создавать и распоряжаться ею каждый раз, когда вы перемещаете мышь.


вам нужно сохранить свою линию где-то.

шаги, которые вам нужно предпринять:

  1. создайте где-нибудь, чтобы сохранить свои очки в основном классе, e.г. Ан ArrayList<ArrayList<Point>> - где каждая ArrayList<Point> содержит список точек в одну линию.
  2. дождитесь событий mousedown и создайте массив для новой строки (e.g a new ArrayList<Point>) в конце списка строк
  3. дождитесь событий mousemoved и добавьте точку в последнюю строку списка, когда мышь тащится. попросите обновить окно здесь.
  4. в своем paint, повторите все строки и нарисуйте каждую точку каждой строки в массиве.
  5. чтобы очистить чертеж, просто замените массив пустым списком и обновите окно.

если вы не храните свои линии где-то, они будут потеряны. Это имеет смысл?

другой способ хранения строк с помощью Canvas объект, где пиксель-карта того, что нарисовано вспомнил и автоматически. Если вы не возражаете, чтобы ваши линейные данные не были векторными точками, и вы также можете использовать изображения или цвета, то это может быть лучшим подходом.


Я написал решение некоторое время назад о том, как нарисовать линию с помощью движений мыши. Это должно сработать для тебя.

  Point mAnchorPoint = new Point(200, 200);
  Point mPreviousPoint = Point.Empty;

  private void panel1_MouseMove(object sender, MouseEventArgs e)
  {
     if (mPreviousPoint != Point.Empty)
     {
        // Clear last line drawn
        ControlPaint.DrawReversibleLine(PointToScreen(mAnchorPoint), PointToScreen(mPreviousPoint), Color.Pink);
     }

     // Update previous point
     mPreviousPoint = e.Location;
     mPreviousPoint.Offset(myPanel1.Location);

     // Draw the new line
     ControlPaint.DrawReversibleLine(PointToScreen(mAnchorPoint), PointToScreen(mPreviousPoint), Color.Pink);
  }

в основном то, что вы можете сделать, это нарисовать линию каждый раз, когда мышь перемещается. Если была предыдущая линия и вы все еще двигаете мышью, сотрите линию и нарисуйте новую. Обратите внимание, что этот пример смещает на основе определенного Panel (myPanel1 в этом примере). Отрегулируйте соответственно. Если вы измените размер элемента управления, вам нужно будет перерисовать линию использование точки привязки предыдущая точка.