copiando dibujo a mano libre del panel en visual studio 2013

Quiero dibujar la mano libre en un formulario (cuadro de imagen) en el estudio visual y copiar la misma figura (que dibujo) en otro cuadro de panel / imagen. Además, no deberían ser puntos formando una línea, sino una línea continua. Por favor ayuda.

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { Pen p_white; bool draw = true; private Graphics objgraphics; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { } private void panel1_Paint(object sender, PaintEventArgs e) { Pen p_black = new Pen(new SolidBrush(Color.Black)); if (draw) { objgraphics = panel1.CreateGraphics(); } } /*private void panel1_MouseDown(object sender, MouseEventArgs e) { bool draw = true; }*/ private void panel1_MouseMove_1(object sender, MouseEventArgs e) { Rectangle rEllipse = new Rectangle(); switch (e.Button) { case MouseButtons.Left: rEllipse.X = eX; rEllipse.Y = eY; rEllipse.Width = 5; rEllipse.Height = 5; objgraphics.DrawEllipse(System.Drawing.Pens.Black, rEllipse); break; case MouseButtons.Right: rEllipse.X = eX; rEllipse.Y = eY; rEllipse.Width = 3; rEllipse.Height = 3; objgraphics.DrawEllipse(System.Drawing.Pens.Black, rEllipse); break; default: return; } } /*private void panel1_MouseUp(object sender, MouseEventArgs e) { bool draw = false; } */ private void form_Paint(object sender, EventArgs e) { } private void panel2_Paint(object sender, PaintEventArgs e) { Pen p_black = new Pen(new SolidBrush(Color.Black)); if (draw) { objgraphics = panel1.CreateGraphics(); } } private void button2_Click(object sender, EventArgs e) { this.Close(); } } } 

Al mirar tu código, me temo que tengo que decir: todo esto está mal .

Perdón por ser tan directo, pero nunca debes usar el control. ¡Crea Gráficos!

  • Lo primero que debe hacer es descartar el objeto Graphics objgraphics .

¡Es (casi) siempre incorrecto almacenar un objeto Graphics !

En su lugar, debe usar la que obtiene del parámetro e.Graphics en los eventos Paint de sus controles.

Tenga en cuenta que Graphics no contiene ningún gráfico, es una herramienta utilizada para dibujar en un Bitmap asociado o en la superficie de un control.

  • Lo siguiente que hay que hacer es entender sobre dibujar líneas a mano alzada. A menudo uno puede ver el código que tiene; pero es inútil y solo un ejemplo de cuantas cosas estúpidas encuentras en las presentaciones. Olvídalo. Siempre se verá como una porquería ya que los círculos simplemente nunca se ven suaves y tan pronto como muevas el mouse más rápido las pseudo líneas se desmoronan por completo.

Hay un buen método DrawCurve que dibujará líneas suaves. Le das un Pen y una matriz de Points .

Esto es lo que usaremos.

Volvamos a lo básico: ¿cómo crear un gráfico? Ahora sabemos que debe llamar a DrawCurve en el evento Paint :

 e.Graphics.DrawCurve(somePen, somePointsArray); 

Esto trae a colación las siguientes preguntas:

  • ¿Qué es algo?
  • ¿Qué es unPointsArray?

Hay una tercera pregunta oculta:

  • ¿Qué hay de dibujar más líneas?

El primero es simple; creas un Pen con un ancho de trazo de 5.5 píxeles como

 Pen somePen = new Pen(Color.Blue, 5.5f); 

Si quieres puedes darle un estilo de vida (guiones) también.

Ahora para la matriz: en su forma más simple, esto también es fácil …

En el evento MouseMove , almacena la Location actual en una lista de puntos. primero lo declaramos a nivel de clase:

 List currentLine = new List(); 

Luego comenzamos a llenarlo siempre que se presione el botón izquierdo:

 private void panel1_MouseMove_1(object sender, MouseEventArgs e) { if (e.Button == System.Windows.Forms.MouseButtons.Left) { currentLine.Add(e.Location); panel1.Invalidate(); } } 

Tenga en cuenta la última línea: la Invalidate de Invalidate en un control activa el sistema para invocar el evento Paint . Puede parecer complicado, pero esta es la única forma correcta, ya que garantiza que el mismo dibujo también ocurrirá cuando algún otro motivo lo haga necesario.

Necesitamos dibujar porque tenemos cambios en los datos que se deben dibujar. Pero hay muchas razones externas , la más conocida es la secuencia Minimize/maximize que borrará el dibujo y activará el evento Paint también. ¡Entonces tenemos que cooperar con la forma en que Windows extrae sus controles! Solo así los gráficos persistirán .

También tenga en cuenta que no usamos una matriz ya que no sabemos cuántos Points necesitaremos. En su lugar usamos una List y luego la lanzamos a Array .

Permite codificar el evento Paint para nuestro caso simple:

 private void panel1_Paint(object sender, PaintEventArgs e) { using (Pen somePen = new Pen(Color.Blue, 5.5f) ) if (currentLine.Count > 1) e.Graphics.DrawCurve(yourPen , currentLine.ToArray()); } 

Tenga en cuenta que he creado el Pen en una cláusula using . Esta es una forma económica y segura de garantizar que el Pen se elimine correctamente.

¡También tenga en cuenta cómo lanzamos la List a una Array !

El código anterior solo funcionaría y le permitiría dibujar una línea a mano alzada.

¿Pero qué pasa con la siguiente línea? ¡No debería conectarse con el primero así que no podemos agregar más puntos!

Así que no solo necesitamos una lista de puntos sino más que eso, de hecho, se necesita una lista de puntos:

 List> curves = new List>(); 

Y agregamos la curva actual cada vez que se suelta el mouse:

 private void panel1_MouseUp(object sender, MouseEventArgs e) { if (currentLine.Count > 1) curves.Add(currentLine.ToList()); // copy!! currentLine.Clear(); panel1.Invalidate(); } 

Fíjese cómo utilizo un molde de List to List para aplicar una copia o, de lo contrario, solo se asignará la referencia y luego, en la siguiente línea borrada.

De nuevo activamos el evento Paint como la última cosa para hacer.

Ahora debemos cambiar el evento Paint para mostrar todas las líneas, tanto la que se está dibujando actualmente como todas las anteriores …:

 private void panel1_Paint(object sender, PaintEventArgs e) { using (Pen somePen = new Pen(Color.Blue, 5.5f) ) { if (currentLine.Count > 1) e.Graphics.DrawCurve(somePen, currentLine.ToArray()); foreach (List lp in curves) if (lp.Count > 1) e.Graphics.DrawCurve(somePen, lp.ToArray()); } } 

Ahora, básicamente, hemos terminado con la parte de dibujo a mano alzada.

Así que volvemos a su pregunta original: ¿cómo puede copiar el dibujo a un segundo Panel ?

Bueno, has almacenado todo en la estructura de datos de las curves .

Por lo tanto, tiene dos opciones: utilizar simplemente los mismos datos en el evento panel2_Paint o si necesita copiar y cambiar los datos para adaptarlos a un tamaño diferente.

SO no es un servicio de escritura de código. Así que, por lo general, no debería daros más indicios de lo que escribí en los comentarios anteriores. Pero como esta pregunta surge con tanta frecuencia, escribí el código completo para una aplicación de doodle muy básica.

Aquí hay cosas que todavía faltan:

  • Guardando los datos, guardando el dibujo ( Serialize , DrawToBitMap )
  • Dibujar con plumas y colores variables (cree una clase drawAction para almacenar todo lo que necesite)
  • Usar otras herramientas como Line o Rectangle (crear una clase drawAction )
  • Despejando el dibujo (ver a continuación)
  • Deshacer y Rehacer (mira en Stacks an Queues )
  • Almacenamiento en caché cuando hay una gran cantidad de líneas (dibuja la primera porción en un BackgroundImage Bitmap )

Aquí hay un código de compensación:

 curves.Clear(); currentLine .Clear(); panel1.Invalidate(); 

Noté que su código original le permite dibujar con dos anchos de trazo diferentes usando el botón izquierdo y derecho. Esto solo muestra que este código no es muy bueno. ¿Quién podría a) pensar en eso yb) estar satisfecho con solo dos anchos de trazo?

Por favor, lea esta publicación donde explico un poco sobre la creación de una clase que puede almacenar un ancho de pluma, un color, etc. para que pueda cambiar luego entre las líneas que dibuja.