Как нарисовать линию от точки к точке в C# с помощью панели, графики и точек

#c# #line #panel #point

Вопрос:

Проблема

У меня есть список точек, которые я хочу нарисовать на панели, у меня есть метод проверки, является ли предыдущая точка нулевой, если она не равна нулю, то предполагается провести новую линию от предыдущей точки к следующей точке. Вместо этого , когда я нажимаю на кнопку initialize_shape , вывод, который я получаю, представляет собой одну линию, соединяющую две точки, остальные точки отображаются, но между ними нет линии.

Ожидания

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

Код

  public partial class Form1 : Form
    {
 //declare the lists that will hold the points
        List<Point> Shape1 = new List<Point>();
//this method belongs to a button object that draws the shape
 private void button1_Click(object sender, EventArgs e)
        {
            Shape1.Clear();
            Shape2.Clear();
            Point p1a = new Point(20, 30);
            Point p2a = new Point(120,50);
            Point p3a = new Point(160,80);
            Point p4a = new Point(180, 300);
            Point p5a = new Point(100,220);
            Point p6a = new Point(50, 280);
            Point p7a = new Point(20, 140);
            //Hold the Points in an array
            Point[] mypoints = new Point[] {p1a,p2a,p3a,p4a,p5a,p6a,p7a};
            //add the points to the List with one call
            Shape1.AddRange(mypoints);
            //the pens are added here
            Pen pBlue = new Pen(Brushes.Blue, 1);
            Pen pRED = new Pen(Brushes.Red, 1);
            //The panel object used below is a control that was added to the form
            Graphics g = panel1.CreateGraphics();
            DisplayShape(Shape1, pBlue, g);
           }
       //This method is supposed to draw lines between the points on the 
       //Panel
         void DisplayShape(List<Point> Shp,Pen pen, Graphics G)
        {
            Point? prevPoint = null;//nullable
            foreach(Point pt in Shp)
            {
                G.DrawEllipse(pen, new Rectangle(pt.X - 2, pt.Y - 2, 4, 4));
                //something in this logic is not right
                if (prevPoint != null)
                {
                    G.DrawLine(pen, (Point)prevPoint, pt);
                    prevPoint = pt;
                }
                G.DrawLine(pen, Shp[0], Shp[Shp.Count - 1]);
            }

        }
  //this method intializes the form
  public Form1()
        {
            InitializeComponent();   
        }
}
 

Выход

введите описание изображения здесь

Комментарии:

1. Могут быть и другие проблемы, но мне кажется, что последние DrawLine() должны быть за пределами foreach .

2. @500-InternalServerError, Спасибо, что попробовали это немного

3. Графика g = панель 1. CreateGraphics(); Обычно это действительно плохая идея, так как результирующая графика не будет постоянной. Вместо этого нарисуйте событие Paint и используйте там объект e.Graphics. Вы также можете использовать непостоянные строки, используя g.DrawLines() (множественное число!), Но любая последовательность минимизации/максимизации очистит их..

4. Ага. Вам нужно следовать правилам GDI grpahics: Рисуйте только в/из события Paint с помощью параметра e.Graphics. Вам нужно будет где-то сохранить все необходимые параметры; также используйте Invalidate для запуска Paint при необходимости, т. Е. Всякий раз, когда параметры меняются!

5. Point это структура, и ее никогда не будет null . Проверьте, Point.Empty может быть, вместо этого.

Ответ №1:

Этот код

 if (prevPoint != null)
{
      G.DrawLine(pen, (Point)prevPoint, pt);
      prevPoint = pt;
}
 

никогда не будет выполняться, так как prevPoint устанавливается только внутри оператора if. Это должно быть

 if (prevPoint != null)
{
      G.DrawLine(pen, (Point)prevPoint, pt);
}
prevPoint = pt;
 

или пропустите начальную точку

 if(Shp.Count < 2) return;
var prevPoint = Shp[0];
foreach(Point pt in Shp.Skip(1)){
    G.DrawLine(pen, prevPoint, pt);
}
 

Также обратите внимание, что:

  • G.DrawLine(pen, Shp[0], Shp[Shp.Count - 1]); всегда будет рисовать одно и то же, поэтому не нужно находиться внутри цикла
  • Рисование внутри обработчика событий кнопки, вероятно, не лучший способ, так как при перерисовке элемента управления все будет очищено. Я бы предложил прикрепить обработчик события к событию paint. Или создайте подкласс вашей панели с переопределением OnPaint

Комментарии:

1. Это гениально, это сработало, Спасибо