none
Predibujado de lineas siempre comienza en el punto anterior al punto de inicio del dibujo RRS feed

  • Pregunta

  • Hola Amigos del Foro,

    Tengo el siguiente código que traza lineas y rectangulos en un picturebox de WinForm mediante dos clase, clase Shape y clase Figura. Cuando doy click en el primer punto extremo, se inicia el predibujado de una linea que va desde el punto clickeado hasta la posición del puntero del mouse, esta linea se dibuja dinamicamente en linea discontinua y sigue el movimiento del mouse, una vez que se hace el segundo click, se dibuja la linea definitiva. El problema principal es que luego que se crea la linea definitiva, la nueva linea a predibujar inicia en el primer punto del la linea definitiva dibujada anteriormente, cuando debe iniciar en el segundo extremo de la mensionada linea o suspenderse hasta que se de click en el primer extremo de la siguiente linea. La misma situación ocurre cuando dibujo los rectangulos. Ver código siguiente:

    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Windows.Forms;
    
    namespace TrazarLineasEnPictureBox
    {
    	/// <summary>
    	/// Description of MainForm.
    	/// </summary>
    	public partial class MainForm : Form
    	{
    		List<Shape> Shapes;
    		List<Figura> Figuras;
    		List<PointF> Pt1, Pt1R;
    		List<PointF> Pt2, Pt2R;
    		Shape newShapes;
    		Figura newRect;
    		PointF pt1p, pt2p, pt1R, pt2R;
    		PointF ptemp;
    		int figura;
    		Graphics g;
    		
    		public MainForm()
    		{
    			InitializeComponent();
    		}
    		void picCanva_MouseDown(object sender, MouseEventArgs e)
    		{
    	
    		}
    		void picCanva_MouseMove(object sender, MouseEventArgs e)
    		{
    			if (figura == 1) {
    				ptemp = (e.Location);
    				if (newShapes != null) {
    					newShapes.pt2 = (e.Location);
    					pt2p = newShapes.pt2;
    					picCanva.Invalidate();
    				}
    			}
    			else if (figura == 2) {
    				ptemp = (e.Location);
    				if (newRect != null) {
    					newRect.pt2 = (e.Location);
    					pt2R = newRect.pt2;
    					picCanva.Invalidate();
    				}
    			}
    			picCanva.Invalidate();
    		}
    		void picCanva_MouseClick(object sender, MouseEventArgs e)
    		{
    			// Sub-rutina para determinar los puntos extremos del segmento de linea
    			if (figura == 1)
    			{
    				if (newShapes == null)
    				{
    					newShapes = new Shape()
    					{
    						pt1 = (e.Location),
    						pt2 = (e.Location)
    					};
    					pt1p = newShapes.pt1;
    				}
    				else
    				{
    					if (newShapes.pt1 != newShapes.pt2)
    					{
    						Shapes.Add(newShapes);
    					}
    					newShapes = null;
    				}
    			}
    			// Sub-rutina para determinar los puntos superior izquierdo e inferior derecho de rectangulo
    			else if (figura == 2)
    			{
    				if (newRect == null)
    				{
    					newRect = new Figura(g)
    					{
    						pt1 = (e.Location),
    						pt2 = (e.Location)
    					};
    					pt1R = newRect.pt1;
    				}
    				else
    				{
    					if (newRect.pt1 != newRect.pt2)
    					{
    						Figuras.Add(newRect);
    					}
    					newRect = null;
    				}
    			}
    			picCanva.Refresh();
    		}
    		void btnLinea_Click(object sender, EventArgs e)
    		{
    			figura = 1;// Indica que se esta dibujando una linea
    		}
    		void btnRect_Click(object sender, EventArgs e)
    		{
    			figura = 2;// Indica que se esta dibujando un rectangulo
    		}
    		void MainForm_Load(object sender, EventArgs e)
    		{
    			Shapes = new List<Shape>();  // Lista de lineas
    			Figuras = new List<Figura>(); // Lista de rectangulos
    			Pt1 = new List<PointF>();
    			Pt2 = new List<PointF>();
    			Pt1R = new List<PointF>();
    			Pt2R = new List<PointF>();
    		}
    		void picCanva_Paint(object sender, PaintEventArgs e)
    		{
    			g = e.Graphics;
    			e.Graphics.Clear(picCanva.BackColor);
    			g.SmoothingMode = SmoothingMode.AntiAlias;
    			float[] dashValues = { 5, 3 };
    			Pen psel = new Pen(Color.WhiteSmoke, 1);
    			Pen p = new Pen(Color.YellowGreen, 1);
    			psel.DashPattern = dashValues;
    			
    			// Aqui se colocan los puntos en las listas de puntos.
    			if (newShapes != null) newShapes.Draw(g);
    			for (int i = 0; i < Shapes.Count; i++) {
    				Pt1.Add(Shapes[i].pt1);
    				Pt2.Add(Shapes[i].pt2);
    			}
    			// Aqui se colocan los puntos en las listas de puntos.
    			if (newRect != null) newRect.DrawRectangulo(g);
    			for (int i = 0; i < Figuras.Count; i++) {q
    				Pt1R.Add(Figuras[i].pt1);
    				Pt2R.Add(Figuras[i].pt2);
    			}
    			
    			if (figura == 1)
    			{
    //				// Aqui se predibuja el segmento de linea hasta el punto provisional.
    				if(ptemp == pt2p) return;
    				g.DrawLine(psel, pt1p, ptemp);
    			}
    			if (figura == 2)
    			{
    				// Predibuja el rectangulo correspondiente a las losas
    				using (SolidBrush brFig = new SolidBrush(Color.Gray)) {
    					RectangleF rectFig = new RectangleF(pt1R, new SizeF((ptemp.X - pt1R.X),(ptemp.Y - pt1R.Y)));
    					g.FillRectangle(brFig, rectFig);
    				}
    			}
    			// Rutina para dibujar los segmentos de lineas
    			for (int i = 0; i < Pt1.Count; i++) {
    				g.DrawLine(p, Pt1[i], Pt2[i]);
    			}
    			// Rutina para dibujar los rectangulos correspondientes a las losas
    			for (int i = 0; i < Pt1R.Count; i++) {
    				RectangleF LosaRtg = new RectangleF(Pt1R[i], new SizeF((Pt2R[i].X-Pt1R[i].X),
    				                                                     (Pt2R[i].Y-Pt1R[i].Y)));
    				g.FillRectangle(new SolidBrush(Color.Gold), LosaRtg);
    			}
    		}
    		void BtnSalir_Click(object sender, EventArgs e)
    		{
    			Close();
    		}
    	}
    }

    Código de clase Shape

                                                               
    using System;
    using System.Drawing;
    
    namespace TrazarLineasEnPictureBox
    {
    	/// <summary>
    	/// Description of Shape.
    	/// </summary>
    	public class Shape
    	{
    		public  PointF pt1{ get; set; }
    		public  PointF pt2{ get; set; }
    		Pen psel = new Pen(Color.WhiteSmoke, 1);
    
    		public void Draw(Graphics g)
    		{
    			g.DrawLine(psel, pt1, pt2);
    		}
    	}
    }


    Código de clase Figura

    using System; using System.Drawing; namespace TrazarLineasEnPictureBox { /// <summary> /// Description of Figura. /// </summary> public class Figura { public PointF pt1 { get; set;} public PointF pt2 { get; set;} public Color color = Color.Yellow; private Graphics g; public Figura() { //Constructor sin parametro } public Figura(Graphics _g) { this.g = _g; } public void DrawRectangulo(Graphics g) { using (SolidBrush br = new SolidBrush(Color.FromArgb(20, 224, 224, 90))) { RectangleF rect = new RectangleF(pt1,new SizeF((pt2.X-pt1.X),(pt2.Y-pt1.Y))); g.FillRectangle(br,rect); } } } }



    MLiranzo

    viernes, 18 de septiembre de 2020 20:44

Respuestas

  • Hola Marino

    Sólo modifiqué 2 o 3 cosas para que funcione bien, básicamente que no repinte el PictureBox constantemente en el evento MouseMove, o sea el programa estaba bastante bien hecho salvo ese error conceptual, y la técnica de programación no se si es la mejor pero no está nada mal.

    Copio el código con muy pocas correcciones comentadas. Sólo toqué el MainForm.cs.

    Al principio la variable figura vale 0, por lo que hay que clickear el botón Linea o Rect para comenzar, o no dibujará nada.

    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Windows.Forms;
    
    namespace TrazarLineasEnPictureBox
    {
        public partial class MainForm : Form
        {
            List<Shape> Shapes;
            List<Figura> Figuras;
            List<PointF> Pt1, Pt1R;
            List<PointF> Pt2, Pt2R;
            Shape newShapes;
            Figura newRect;
            PointF pt1p, pt2p, pt1R, pt2R;
            PointF ptemp;
            int figura;
            Graphics g;
            bool isDrawing = false;
    
            public MainForm()
            {
                InitializeComponent();
            }
    
            void picCanva_MouseDown(object sender, MouseEventArgs e)
            {
    
            }
    
            void picCanva_MouseMove(object sender, MouseEventArgs e)
            {
                if (figura == 1)
                {
                    ptemp = (e.Location);
                    if (newShapes != null)
                    {
                        newShapes.pt2 = (e.Location);
                        pt2p = newShapes.pt2;
                        picCanva.Invalidate();
                    }
                }
                else if (figura == 2)
                {
                    ptemp = (e.Location);
                    if (newRect != null)
                    {
                        newRect.pt2 = (e.Location);
                        pt2R = newRect.pt2;
                        picCanva.Invalidate();
                    }
                }
    
                if (isDrawing)              // Al mover el mouse sólo se repinta si estoy "predibujando", o sea 
                    picCanva.Invalidate();  // luego de clickear el punto inicial y hasta clickear el punto final
            }
    
            void picCanva_MouseClick(object sender, MouseEventArgs e)
            {
                isDrawing = !isDrawing;
                // cuando hago click para iniciar un gráfico se pone a true, y cuando
                // clickeo el punto final vuelve a false. Para saber cuando pintar.
    
                // Sub-rutina para determinar los puntos extremos del segmento de linea
                if (figura == 1)
                {
                    if (newShapes == null)
                    {
                        newShapes = new Shape()
                        {
                            pt1 = (e.Location),
                            pt2 = (e.Location)
                        };
                        pt1p = newShapes.pt1;
                    }
                    else
                    {
                        if (newShapes.pt1 != newShapes.pt2)
                        {
                            Shapes.Add(newShapes);
                        }
                        newShapes = null;
                    }
                }
                // Sub-rutina para determinar los puntos superior izquierdo e inferior derecho de rectangulo
                else if (figura == 2)
                {
                    if (newRect == null)
                    {
                        newRect = new Figura(g)
                        {
                            pt1 = (e.Location),
                            pt2 = (e.Location)
                        };
                        pt1R = newRect.pt1;
                    }
                    else
                    {
                        if (newRect.pt1 != newRect.pt2)
                        {
                            Figuras.Add(newRect);
                        }
                        newRect = null;
                    }
                }
                picCanva.Invalidate();
            }
    
            void btnLinea_Click(object sender, EventArgs e)
            {
                figura = 1;// Indica que se esta dibujando una linea
            }
    
            void btnRect_Click(object sender, EventArgs e)
            {
                figura = 2;// Indica que se esta dibujando un rectangulo
            }
    
            void MainForm_Load(object sender, EventArgs e)
            {
                Shapes = new List<Shape>();  // Lista de lineas
                Figuras = new List<Figura>(); // Lista de rectangulos
                Pt1 = new List<PointF>();
                Pt2 = new List<PointF>();
                Pt1R = new List<PointF>();
                Pt2R = new List<PointF>();
            }
    
            void picCanva_Paint(object sender, PaintEventArgs e)
    		{
    			g = e.Graphics;
    			e.Graphics.Clear(picCanva.BackColor);
    			g.SmoothingMode = SmoothingMode.AntiAlias;
    			float[] dashValues = { 5, 3 };
    			Pen psel = new Pen(Color.Brown, 1); // cambio el color para que se pueda ver bien
    			Pen p = new Pen(Color.YellowGreen, 1);
    			psel.DashPattern = dashValues;
    			
    			// Aqui se colocan los puntos en las listas de puntos.
    			if (newShapes != null) newShapes.Draw(g);
    			for (int i = 0; i < Shapes.Count; i++) {
    				Pt1.Add(Shapes[i].pt1);
    				Pt2.Add(Shapes[i].pt2);
    			}
    			// Aqui se colocan los puntos en las listas de puntos.
    			if (newRect != null) newRect.DrawRectangulo(g);
    			for (int i = 0; i < Figuras.Count; i++) {
    				Pt1R.Add(Figuras[i].pt1);
    				Pt2R.Add(Figuras[i].pt2);
    			}
    			
    			if (figura == 1)
    			{
    //				// Aqui se predibuja el segmento de linea hasta el punto provisional.
    				// if(ptemp == pt2p) return; -> Esto no va porque la variable isDrawing previene de pintar si vale false
                    //                           -> Si no, esto haría que no se dibuje nada. El asunto es que saqué el Invalidate()
                    //                           -> del método MouseMove porque lo pintaba a cada instante y es innecesario
    				g.DrawLine(psel, pt1p, ptemp);
    			}
    			else if (figura == 2) // agrego el else, porque nunca van a ser los 2
    			{
    				// Predibuja el rectangulo correspondiente a las losas
    				using (SolidBrush brFig = new SolidBrush(Color.Gray)) {
    					RectangleF rectFig = new RectangleF(pt1R, new SizeF((ptemp.X - pt1R.X),(ptemp.Y - pt1R.Y)));
    					g.FillRectangle(brFig, rectFig);
    				}
    			}
    			// Rutina para dibujar los segmentos de lineas
    			for (int i = 0; i < Pt1.Count; i++) {
    				g.DrawLine(p, Pt1[i], Pt2[i]);
    			}
    			// Rutina para dibujar los rectangulos correspondientes a las losas
    			for (int i = 0; i < Pt1R.Count; i++) {
    				RectangleF LosaRtg = new RectangleF(Pt1R[i], new SizeF((Pt2R[i].X-Pt1R[i].X),
    				                                                     (Pt2R[i].Y-Pt1R[i].Y)));
    				g.FillRectangle(new SolidBrush(Color.Gold), LosaRtg);
    			}
    		}
    
            void BtnSalir_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }

    Saludos

    Pablo


    • Marcado como respuesta MLiranzo sábado, 19 de septiembre de 2020 15:25
    sábado, 19 de septiembre de 2020 12:38

Todas las respuestas

  • Hola MLiranzo, 

      

    Gracias por levantar tu consulta en los foros de MSDN. Vamos a darle seguimiento a tu caso.  

    Cualquier duda referente a productos Microsoft, puedes consultarnos. Es un gusto informarte. 

    Gracias por usar los foros de MSDN.   

    Eric Ruiz 

     ____________________________ 

      

    Por favor recuerde "Marcar como respuesta" las respuestas que hayan resuelto su problema, es una forma común de reconocer a aquellos que han ayudado, y hace que sea más fácil para los otros visitantes encontrar la solución más tarde.  

    Microsoft ofrece este servicio de forma gratuita, con la finalidad de ayudar a los usuarios y la ampliación de la base de datos de conocimientos relacionados con los productos y tecnologías de Microsoft.   

    Este contenido es proporcionado "tal cual" y no implica ninguna responsabilidad de parte de Microsoft. 

    sábado, 19 de septiembre de 2020 1:29
    Moderador
  • Hola Marino

    Sólo modifiqué 2 o 3 cosas para que funcione bien, básicamente que no repinte el PictureBox constantemente en el evento MouseMove, o sea el programa estaba bastante bien hecho salvo ese error conceptual, y la técnica de programación no se si es la mejor pero no está nada mal.

    Copio el código con muy pocas correcciones comentadas. Sólo toqué el MainForm.cs.

    Al principio la variable figura vale 0, por lo que hay que clickear el botón Linea o Rect para comenzar, o no dibujará nada.

    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Windows.Forms;
    
    namespace TrazarLineasEnPictureBox
    {
        public partial class MainForm : Form
        {
            List<Shape> Shapes;
            List<Figura> Figuras;
            List<PointF> Pt1, Pt1R;
            List<PointF> Pt2, Pt2R;
            Shape newShapes;
            Figura newRect;
            PointF pt1p, pt2p, pt1R, pt2R;
            PointF ptemp;
            int figura;
            Graphics g;
            bool isDrawing = false;
    
            public MainForm()
            {
                InitializeComponent();
            }
    
            void picCanva_MouseDown(object sender, MouseEventArgs e)
            {
    
            }
    
            void picCanva_MouseMove(object sender, MouseEventArgs e)
            {
                if (figura == 1)
                {
                    ptemp = (e.Location);
                    if (newShapes != null)
                    {
                        newShapes.pt2 = (e.Location);
                        pt2p = newShapes.pt2;
                        picCanva.Invalidate();
                    }
                }
                else if (figura == 2)
                {
                    ptemp = (e.Location);
                    if (newRect != null)
                    {
                        newRect.pt2 = (e.Location);
                        pt2R = newRect.pt2;
                        picCanva.Invalidate();
                    }
                }
    
                if (isDrawing)              // Al mover el mouse sólo se repinta si estoy "predibujando", o sea 
                    picCanva.Invalidate();  // luego de clickear el punto inicial y hasta clickear el punto final
            }
    
            void picCanva_MouseClick(object sender, MouseEventArgs e)
            {
                isDrawing = !isDrawing;
                // cuando hago click para iniciar un gráfico se pone a true, y cuando
                // clickeo el punto final vuelve a false. Para saber cuando pintar.
    
                // Sub-rutina para determinar los puntos extremos del segmento de linea
                if (figura == 1)
                {
                    if (newShapes == null)
                    {
                        newShapes = new Shape()
                        {
                            pt1 = (e.Location),
                            pt2 = (e.Location)
                        };
                        pt1p = newShapes.pt1;
                    }
                    else
                    {
                        if (newShapes.pt1 != newShapes.pt2)
                        {
                            Shapes.Add(newShapes);
                        }
                        newShapes = null;
                    }
                }
                // Sub-rutina para determinar los puntos superior izquierdo e inferior derecho de rectangulo
                else if (figura == 2)
                {
                    if (newRect == null)
                    {
                        newRect = new Figura(g)
                        {
                            pt1 = (e.Location),
                            pt2 = (e.Location)
                        };
                        pt1R = newRect.pt1;
                    }
                    else
                    {
                        if (newRect.pt1 != newRect.pt2)
                        {
                            Figuras.Add(newRect);
                        }
                        newRect = null;
                    }
                }
                picCanva.Invalidate();
            }
    
            void btnLinea_Click(object sender, EventArgs e)
            {
                figura = 1;// Indica que se esta dibujando una linea
            }
    
            void btnRect_Click(object sender, EventArgs e)
            {
                figura = 2;// Indica que se esta dibujando un rectangulo
            }
    
            void MainForm_Load(object sender, EventArgs e)
            {
                Shapes = new List<Shape>();  // Lista de lineas
                Figuras = new List<Figura>(); // Lista de rectangulos
                Pt1 = new List<PointF>();
                Pt2 = new List<PointF>();
                Pt1R = new List<PointF>();
                Pt2R = new List<PointF>();
            }
    
            void picCanva_Paint(object sender, PaintEventArgs e)
    		{
    			g = e.Graphics;
    			e.Graphics.Clear(picCanva.BackColor);
    			g.SmoothingMode = SmoothingMode.AntiAlias;
    			float[] dashValues = { 5, 3 };
    			Pen psel = new Pen(Color.Brown, 1); // cambio el color para que se pueda ver bien
    			Pen p = new Pen(Color.YellowGreen, 1);
    			psel.DashPattern = dashValues;
    			
    			// Aqui se colocan los puntos en las listas de puntos.
    			if (newShapes != null) newShapes.Draw(g);
    			for (int i = 0; i < Shapes.Count; i++) {
    				Pt1.Add(Shapes[i].pt1);
    				Pt2.Add(Shapes[i].pt2);
    			}
    			// Aqui se colocan los puntos en las listas de puntos.
    			if (newRect != null) newRect.DrawRectangulo(g);
    			for (int i = 0; i < Figuras.Count; i++) {
    				Pt1R.Add(Figuras[i].pt1);
    				Pt2R.Add(Figuras[i].pt2);
    			}
    			
    			if (figura == 1)
    			{
    //				// Aqui se predibuja el segmento de linea hasta el punto provisional.
    				// if(ptemp == pt2p) return; -> Esto no va porque la variable isDrawing previene de pintar si vale false
                    //                           -> Si no, esto haría que no se dibuje nada. El asunto es que saqué el Invalidate()
                    //                           -> del método MouseMove porque lo pintaba a cada instante y es innecesario
    				g.DrawLine(psel, pt1p, ptemp);
    			}
    			else if (figura == 2) // agrego el else, porque nunca van a ser los 2
    			{
    				// Predibuja el rectangulo correspondiente a las losas
    				using (SolidBrush brFig = new SolidBrush(Color.Gray)) {
    					RectangleF rectFig = new RectangleF(pt1R, new SizeF((ptemp.X - pt1R.X),(ptemp.Y - pt1R.Y)));
    					g.FillRectangle(brFig, rectFig);
    				}
    			}
    			// Rutina para dibujar los segmentos de lineas
    			for (int i = 0; i < Pt1.Count; i++) {
    				g.DrawLine(p, Pt1[i], Pt2[i]);
    			}
    			// Rutina para dibujar los rectangulos correspondientes a las losas
    			for (int i = 0; i < Pt1R.Count; i++) {
    				RectangleF LosaRtg = new RectangleF(Pt1R[i], new SizeF((Pt2R[i].X-Pt1R[i].X),
    				                                                     (Pt2R[i].Y-Pt1R[i].Y)));
    				g.FillRectangle(new SolidBrush(Color.Gold), LosaRtg);
    			}
    		}
    
            void BtnSalir_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }

    Saludos

    Pablo


    • Marcado como respuesta MLiranzo sábado, 19 de septiembre de 2020 15:25
    sábado, 19 de septiembre de 2020 12:38
  • Gracias Pablo,

    Tu solución ha resuelto el problema de mi código.

    MLiranzo


    MLiranzo

    sábado, 19 de septiembre de 2020 15:25