Как правильно нарисовать линию с помощью мыши в C # - PullRequest
8 голосов
/ 12 ноября 2010

Это мой код рисования для рисования пользовательской линии мышью на графике.Можете ли вы помочь мне сделать это правильно?

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

Проблема в том, что когда я изменяю размер формы, моя строка разочаровывается.При каждом событии onPaint происходит сбой.

Ответы [ 4 ]

7 голосов
/ 12 ноября 2010

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

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

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());
        }
    }
}
1 голос
/ 12 ноября 2010

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

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

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 голос
/ 12 ноября 2010

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

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

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

Если вы не сохраните где-нибудь свои строки, они будут потеряны.Имеет ли это смысл?

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

0 голосов
/ 12 ноября 2010

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

  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 в этом примере). Отрегулируйте соответственно. Если вы измените размер элемента управления, вам нужно будет перерисовать линию, используя точку привязки предыдущей точки.

...