30 jun 2010

Dibujar objetos de colores

Con lo aprendido en la clase pasada he creado un pequeño programa de dibujo, esto gracias a la buena sugerencia de Elisa de hacer un programa parecido a Paint, donde pudiéramos crear lineas, rectángulos y elipses. Este programa me tomo tiempo terminarlo y perfeccionarlo para que no provocara errores en su ejecución y que además fuera agradable al usuario.

En esta imagen se puede apreciar la ventana resultante del programa en ejecución.

En el programa es posible dibujar lineas, rectángulos y elipses de tamaños definidos por el usuario mediante el uso del mouse. Además es posible seleccionar el color con que se desea dibujar el objeto.

En la parte superior de la ventana del programa se muestran cuatro botones con diferentes funciones.
El botón Predeterminado restaura los valores originales en el programa. Los valores provocan que el dibujo siguiente sea una línea y el color se establece como negro.
El botón Deshacer elimina el último dibujo realizado en el panel.
El botón Borrar limpia toda la pantalla, es decir elimina todos los objetos creados y además restablece los valores predeterminados.
El botón Salir simplemente cierra la ventana.

En la siguiente imagen se pueden observar los mismos objetos de la imagen anterior pero algunos ya se han eliminado con el botón deshacer y luego se crearon nuevos objetos.

Aquí algunas partes sobresalientes del código.

En la clase auxiliar agregue dos variables más, "COLOR" para guardar el color con que se dibujó el objeto y "SELECT" que guarda un número entero que indica si el objeto fue una línea(1), un rectángulo(2) o un elipse(3).

class Objeto {
 protected double m1, m2, m3, m4;
 protected Color COLOR;
 protected int SELECT;

 public Objeto(double V1, double V2, double V3, double V4,
       Color GUARDADO, int seleccion) {
  this.m1 = V1;
  this.m2 = V2;
  this.m3 = V3;
  this.m4 = V4;
  this.COLOR = GUARDADO;
  this.SELECT = seleccion;
 }
}

Para el botón Deshacer implemente algo sencillo. Sabemos que los valores de cada objeto se están guardando en un arreglo, así que para eliminar el último elemento de este arreglo primero obtuve la cantidad de elementos totales, y como los elementos en el arreglo empiezan desde 0, 1, 2... le reste 1 para obtener la posición del último elemento del arreglo y ya obtenida la posición basta con eliminarla. La condición es para que no provoque errores en el terminal, ya que si no hay elementos en el arreglo y se le pica a deshacer, este no podrá eliminar nada.

if (cmd.equals("DESHACER")) {
   int ultimo = this.objetos.size()-1;
   if (ultimo>=0) {
    this.objetos.remove(ultimo);
   }
   this.repaint();
   System.out.println(this.objetos.size() + " objetos");
  }

Esta fue una parte un tanto complicada e incluso un poco revuelta a primera vista. Lo que hago con esta sección del código es dibujar en la pantalla los objetos ya guardados y el que se esta dibujando actualmente.
El iterador va accediendo a los valores guardados en el arreglo. Uno de los valores es el del color y otro muy importante es el de la selección del objeto.
Algunas de las condiciones lo que hacen es establecer correctamente las posiciones X y Y, así como del ANCHO y ALTURA de los rectángulos y elipses, y que el programa las dibuje correctamente.
En pocas palabras lo que logre con esto fue que después de la selección del objeto rectángulo o elipse, independientemente de donde diera clic inicial y clic final para establecer las medidas del objeto, este se dibujara bien en cualquier posición.

public void paint(Graphics gr) {
  super.paint(gr);
  Graphics2D g = (Graphics2D)gr;

  // Dimensiones actuales
  int ancho = super.getWidth();
  int altura = super.getHeight();

  g.setStroke(Dibujar.GROS);
  Iterator< Objeto > i = this.objetos.iterator();

  // Mientras haya mas elementos en el iterador
  while (i.hasNext()) {
   Objeto l = i.next();
   g.setColor(l.COLOR);
   double Ex = l.m1*ancho;
   double Ey = l.m2*altura;
   double Ea = l.m3*ancho;
   double Eb = l.m4*altura;

   if (l.SELECT == 1) {
    g.draw(new Line2D.Double(l.m1*ancho,
        l.m2*altura,
        l.m3*ancho,
        l.m4*altura));
   }
   if (l.SELECT == 2) {
    if (Ex < Ea && Ey < Eb) {
     g.draw(new Rectangle2D.Double(l.m1*ancho,
        l.m2*altura,
        l.m3*ancho-l.m1*ancho,
        l.m4*altura-l.m2*altura));
    }
    if (Ex > Ea && Ey > Eb) {
     g.draw(new Rectangle2D.Double(l.m3*ancho,
        l.m4*altura,
        l.m1*ancho-l.m3*ancho,
        l.m2*altura-l.m4*altura));
    }
    if (Ex < Ea && Ey > Eb) {
     g.draw(new Rectangle2D.Double(l.m1*ancho,
        l.m4*altura,
        l.m3*ancho-l.m1*ancho,
        l.m2*altura-l.m4*altura));
    }
    if (Ex > Ea && Ey < Eb) {
     g.draw(new Rectangle2D.Double(l.m3*ancho,
        l.m2*altura,
        l.m1*ancho-l.m3*ancho,
        l.m4*altura-l.m2*altura));
    }
   }
   if (l.SELECT == 3) {
    if (Ex < Ea && Ey < Eb) {
     g.draw(new Ellipse2D.Double(l.m1*ancho,
        l.m2*altura,
        l.m3*ancho-l.m1*ancho,
        l.m4*altura-l.m2*altura));
    }
    if (Ex > Ea && Ey > Eb) {
     g.draw(new Ellipse2D.Double(l.m3*ancho,
        l.m4*altura,
        l.m1*ancho-l.m3*ancho,
        l.m2*altura-l.m4*altura));
    }
    if (Ex < Ea && Ey > Eb) {
     g.draw(new Ellipse2D.Double(l.m1*ancho,
        l.m4*altura,
        l.m3*ancho-l.m1*ancho,
        l.m2*altura-l.m4*altura));
    }
    if (Ex > Ea && Ey < Eb) {
     g.draw(new Ellipse2D.Double(l.m3*ancho,
        l.m2*altura,
        l.m1*ancho-l.m3*ancho,
        l.m4*altura-l.m2*altura));
    }
   }
  }

  if (this.dibujando) {
   double Wx = startX*ancho;
   double Wy = startY*altura;
   double Wa = ahoraX*ancho;
   double Wb = ahoraY*altura;

   // Linea actual
   if (seleccion == 1) {
    g.setColor(this.GUARDADO);
    g.draw(new Line2D.Double(this.startX*ancho,
        this.startY*altura,
        this.ahoraX*ancho,
        this.ahoraY*altura));
   }
   // Rectangulo actual
   if (seleccion == 2) {
    if (Wx < Wa && Wy < Wb) {
     g.setColor(this.GUARDADO);
     g.draw(new Rectangle2D.Double(this.startX*ancho,
        this.startY*altura,
        this.ahoraX*ancho-startX*ancho,
        this.ahoraY*altura-startY*altura));
    }
    if (Wx > Wa && Wy > Wb) {
     g.setColor(this.GUARDADO);
     g.draw(new Rectangle2D.Double(this.ahoraX*ancho,
        this.ahoraY*altura,
        this.startX*ancho-ahoraX*ancho,
        this.startY*altura-ahoraY*altura));
    }
    if (Wx < Wa && Wy > Wb) {
     g.setColor(this.GUARDADO);
     g.draw(new Rectangle2D.Double(this.startX*ancho,
        this.ahoraY*altura,
        this.ahoraX*ancho-startX*ancho,
        this.startY*altura-ahoraY*altura));
    }
    if (Wx > Wa && Wy < Wb) {
     g.setColor(this.GUARDADO);
     g.draw(new Rectangle2D.Double(this.ahoraX*ancho,
        this.startY*altura,
        this.startX*ancho-ahoraX*ancho,
        this.ahoraY*altura-startY*altura));
    }
   }
   // Elipse actual
   if (seleccion == 3) {
    if (Wx < Wa && Wy < Wb) {
     g.setColor(this.GUARDADO);
     g.draw(new Ellipse2D.Double(this.startX*ancho,
        this.startY*altura,
        this.ahoraX*ancho-startX*ancho,
        this.ahoraY*altura-startY*altura));
    }
    if (Wx > Wa && Wy > Wb) {
     g.setColor(this.GUARDADO);
     g.draw(new Ellipse2D.Double(this.ahoraX*ancho,
        this.ahoraY*altura,
        this.startX*ancho-ahoraX*ancho,
        this.startY*altura-ahoraY*altura));
    }
    if (Wx < Wa && Wy > Wb) {
     g.setColor(this.GUARDADO);
     g.draw(new Ellipse2D.Double(this.startX*ancho,
        this.ahoraY*altura,
        this.ahoraX*ancho-startX*ancho,
        this.startY*altura-ahoraY*altura));
    }
    if (Wx > Wa && Wy < Wb) {
     g.setColor(this.GUARDADO);
     g.draw(new Ellipse2D.Double(this.ahoraX*ancho,
        this.startY*altura,
        this.startX*ancho-ahoraX*ancho,
        this.ahoraY*altura-startY*altura));
    }
   }
  }
  return;
 }

Descarga desde:
MediaFire: Dibujar.java

2 comentarios:

  1. ¿Y luego botones para guardar a un archivo y abrir un archivo anteriormente guardado? java.io tiene las clases para escribir y leer y podrías crear tu propio formato de archivo que indique por ejemplo con una letra el tipo del objeto, luego en RGB el color y luego las coordenadas requeridas. Estaría padre :)

    ResponderEliminar