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




plano cartesiano en c# (2)

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 unas pocas 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, debe 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 Panel ya que no tiene doublebuffered . En su lugar, use un PictureBox o una Label (con AutoSize=false ) o una subclase de doublebuffered Panel :

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

Notas :

  • No hay tal cosa como una 'Línea' en WinForms, solo píxeles de varios colores. Por lo tanto, para seleccionar una línea, debe almacenar las coordenadas de sus dos puntos finales y luego averiguar si la ha golpeado al hacer clic.

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

  • En cambio, uno podría probar cada línea dibujándola en un mapa de bits y probar el píxel en el que ha hecho clic el mouse. Pero dibujar esos mapas de bits también tendría que hacer matemáticas detrás de escena y también asignar espacio para los mapas de bits, de modo que las matemáticas sean más eficientes.

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

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

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

  • Para seleccionar líneas más delgadas, puede ayudar modificar un poco la distancia.

  • La matemática se tomó directamente de here .

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 y coodLast.


Puede cambiar el color de todo al hacer clic. Mediante el uso de evento de clic de un objeto en particular.

Te doy un ejemplo para el botón. Si hace clic en el botón, el color del panel cambiará. Puede modificar el código según sus requisitos.

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




graphics