c# visual Cómo dibujar una línea y seleccionarla en el Panel




plano cartesiano en c# (2)

Puede cambiar el color de todo al hacer clic. Al usar el evento click de un objeto particular.

Te doy un ejemplo para el botón. Si haces clic en el botón, el color de panal cambiará. Puede modificar el código según su requisito.

private List<Point> coordFirst = new List<Point>();
    private List<Point> coordLast = new List<Point>();
    public Graphics canvas;



    private void Form1_Load(object sender, EventArgs e)
    {
        canvas = panel1.CreateGraphics();
    }





    private void panel1_Click(object sender, EventArgs e)
    {
        panel1.BackColor = Color.Blue;
    }

    private void nonSelectableButton3_Click(object sender, EventArgs e)
    {
        panel1.BackColor = Color.BurlyWood;
    }

Mi programa puede dibujar líneas usando canvas.Drawline (). ¿Cómo hacer clic en la línea y cambiar este color (seleccionar línea)?

private List<Point> coordFirst = new List<Point>();
private List<Point> coordLast = new List<Point>();
public Graphics canvas;

        private void Form1_Load(object sender, EventArgs e)
        {
            canvas=panel1.CreateGraphics();
        }

Línea de coordenadas almacenada en coordFirs & coodLast.


Aquí hay una clase de Line adecuada:

class Line
{
    public Color LineColor { get; set; }
    public float Linewidth { get; set; }
    public bool Selected { get; set; }
    public Point Start { get; set; }
    public Point End { get; set; }

    public Line(Color c, float w, Point s, Point e)
    { LineColor = c; Linewidth = w; Start = s; End = e;    }

    public void Draw(Graphics G)
    { using (Pen pen = new Pen(LineColor, Linewidth)) G.DrawLine(pen, Start, End); }

    public bool HitTest(Point Pt)
    {
        // test if we fall outside of the bounding box:
        if ((Pt.X < Start.X && Pt.X < End.X) || (Pt.X > Start.X && Pt.X > End.X) ||
            (Pt.Y < Start.Y && Pt.Y < End.Y) || (Pt.Y > Start.Y && Pt.Y > End.Y)) 
            return false;
        // now we calculate the distance:
        float dy = End.Y - Start.Y;
        float dx = End.X - Start.X;
        float Z = dy * Pt.X - dx * Pt.Y + Start.Y * End.X - Start.X * End.Y;
        float N = dy * dy + dx * dx;
        float dist = (float)( Math.Abs(Z) / Math.Sqrt(N));
        // done:
        return dist < Linewidth / 2f;
    }

}

Defina una lista para las líneas, probablemente a nivel de clase:

    List<Line> lines = new List<Line>();

Aquí es cómo puede inicializarlo con algunas líneas:

for (int i = 0; i < 20; i++) lines.Add(new Line(Color.Black, 4f, 
    new Point(R.Next(panel1.Width), R.Next(panel1.Height)), 
    new Point(R.Next(panel1.Width), R.Next(panel1.Height))));

Aquí está el resultado de hacer clic en un cruce:

Cada vez que agrega, cambia o elimina una línea, necesita hacer que el Panel refleje las noticias activando el evento Paint :

panel1.Invalidate();

Aquí está el evento Paint del Panel :

private void panel1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
    foreach (Line L in lines) L.Draw(e.Graphics);
}

En el evento MouseClick , haces la prueba:

private void panel1_MouseClick(object sender, MouseEventArgs e)
{
    foreach(Line L in lines) 
            L.LineColor = L.HitTest(e.Location) ?  Color.Red : Color.Black;
    panel1.Invalidate();
}

Para evitar el parpadeo, no use la clase básica del Panel , ya que no está doublebuffered . En su lugar, use una subclase de PictureBox o de doublebuffered Panel :

class DrawPanel : Panel 
{     public DrawPanel ()   { DoubleBuffered = true; }   }

Notas :

  • No existe una 'línea' en WinForms, solo píxeles de varios colores. Entonces, para seleccionar una línea necesita almacenar sus coordenadas de dos puntos finales y luego averiguar si la ha pulsado al hacer clic.

  • El ejemplo anterior muestra cómo hacerlo en matemáticas.

  • En su lugar, se podría probar cada línea dibujándola en un mapa de bits y probando el píxel en el que hizo clic el mouse. Pero dibujar esos mapas de bits tendría que hacer también matemáticas detrás de escena y también asignar espacio para los mapas de bits, por lo que las matemáticas serán más eficientes.

  • Sí, la clase Line parece un poco larga para una cosa tan simple como una línea, pero ¡mira qué cortos son ahora todos los códigos de eventos! ¡Eso es porque las responsabilidades están donde pertenecen!

  • También tenga en cuenta que la primera regla para hacer cualquier dibujo en WinForms es: Nunca almacenar en caché ni almacenar un objeto Grahics . De hecho, nunca debería usar CreateGraphics en primer lugar, ya que el objeto Graphics nunca permanecerá en el alcance y los gráficos que produce no persistirán (es decir, sobrevivirá a una secuencia Minimize-maximizar).

  • También tenga en cuenta cómo distribuyo el objeto e.Graphics de los parámetros del evento Paint a las instancias de Line para que puedan dibujarse con un objeto Graphics actual.

  • Para seleccionar líneas más finas, puede ayudar a modificar un poco la verificación de distancia.

  • La matemática fue tomada directamente de Wikipedia .





graphics