Loading repository data…
Loading repository data…
CrissUD / repository
Clase 13 del curso de Interfaz Gráfica con Java, en donde se muestran conceptos relacionados con el uso de Canvas, como pintar figuras, Áreas y uso de eventos del Mouse sobre el Canvas
Curso propuesto por el grupo de trabajo Semana de Ingenio y Diseño (SID) de la Universidad Distrital Francisco Jose de Caldas.
Cristian Felipe Patiño Cáceres - Estudiante de Ingeniería de Sistemas de la Universidad Distrital Francisco Jose de Caldas
Para continuar con el ejercicio deberá actualizar la carpeta resources/img ya que se han agregado nuevas imágenes. Estas las puede descargar en este mismo repositorio entrando a la carpeta Clase13 seguido de resources/img.
Recordando un poco nuestro recorrido en la clase anterior revisamos el uso de animaciones a traves del objeto Timer, dentro de la exploración de las animación, se vieron temas como Animaciónes para interactividad, Animaciones para muestra de información, Particularidades de animaciónes y diferentes enfoques de animaciones
En esta sesión vamos a ver el uso de Canvas para pintar varias cosas dentro de nuestras interfaces gráficas de una manera introductoria, para explorar a fondo este tema se verán varios items como:
Canvas es un elemento característico de la librería awt de Java y es fundamental para la creación de figuras, animaciónes, imágenes y demás formas que no se podrían construir con los objetos gráficos comunes, hasta el momento los objetos gráficos que hemos manejado hacen parte de la librería Swing de Java, existen diversas opiniones con el uso combinado de estas dos librerías pero no hay de que preocuparse, al fin de cuentas Swing esta totalmente basada en la librería awt por lo que esta pensada desde el inicio a convivir con su antecesora.
El uso de canvas es importante en la creación de Juegos2D ya que este elemento proporciona muchas libertades para plasmar en pantalla y ademas una gran optimización para animaciónes e interacciones con el usuario. También es usado para la representación de gráficas como diagramas de barras, diagrama pastel, lineas temporales, diagramas de Gantt etc. Canvas no es exclusivo de Java, otros lenguajes como JavaScript usan el mismo modelo y tienen los mismos principios para pintar en pantalla.
Vamos a crear un nuevo componente al cual llamaremos Lienzo dentro del paquete components como este será un nuevo componente se creara con sus respectivas clases.
Vamos a realizar la estructura básica del componentes, empezamos con la clase LienzoComponent y como se ha repetido muchas veces, se realizara, la inyección junto al método get correspondiente de su clase compañera.
// Dentro de la clase LienzoComponent
private LienzoTemplate lienzoTemplate;
// Dentro del constructor
lienzoTemplate = new LienzoTemplate(this);
public LienzoTemplate getLienzoTemplate(){
return lienzoTemplate;
}
Ahora vamos con la clase LienzoTemplate, vamos a extender de un objeto tipo Canvas, como este es un objeto gráfico es posible realizar la extensión hacia este tipo de objeto, se debe importar la librería para soportar este tipo de objetos:
import java.awt.Canvas;
public class LienzoTemplate extends Canvas{
}
Vamos a terminar de cellar la inyección:
// Dentro de la clase LienzoTemplate
private LienzoComponent lienzoComponent;
public LienzoTemplate(LienzoComponent lienzoComponent){
this.lienzoComponent = lienzoComponent;
}
También vamos a necesitar del servició RecursosService para obtener varios colores y fuentes:
private RecursosService sRecursos;
// Dentro del constructor
this.sRecursos = RecursosService.getService();
Como este componente esta heredando de un Canvas, es necesario implementar un método especial típico de un canvas el cual es un paint, como estamos heredando y no implementando este método se debe implementar de forma manual y es importante que tenga el decorador @Override o de lo contrario para Java este método será otro método cualquiera:
@Override
public void paint(Graphics g){
}
El decorador @Override indica que es un método implementado, como hemos visto con el uso de los eventos, esté método Paint es un método especial que se ejecuta automáticamente una vez se llama a la clase Template, esto hace parte del ciclo de vida de un canvas y se ejecuta estrictamente después de que se ejecuten las instrucciones del constructor. Si no tiene el decorador mencionado el método será tomado como cualquier otro y se deberá ejecutar manualmente (llamando al método). Por otro lado este método recibe un parámetro de tipo Graphics, este es el objeto que se encargará de pintar en pantalla.
Ahora vamos a configurar las características físicas del componente:
// Detro del constructor
this.setBounds(2, 2, 496, 566);
this.setBackground(Color.WHITE);
this.setVisible(true);
Se puede notar que las coordenadas del componente no están estrictamente al comienzo, están en la posición 2 tanto en X como en Y, esto es por que este lienzo será incorporado dentro del componente Configuraciones específicamente dentro de su panel pDibujo, recordando un poco este panel cuenta con un borde gris de 2 pixeles de grosor, es por esto que el canvas se posicionara desde este punto y ademas se le restaran 4 pixeles de tamaño con respecto al panel contenedor por este motivo, si se dejara desde la posición inicial y al mismo tamaño del panel pDibujo este borde quedaría tapado:
vamos a incorporar el nuevo componente Lienzo al componente Configuraciones, para esto nos ubicamos en la clase ConfiguracionesTemplate y dentro de está realizaremos la declaración, ejemplificación e incorporación:
private LienzoComponent lienzoComponent;
// Dentro del constructor
this.lienzoComponent = new LienzoComponent();
// Dentro del constructor después de la creación de los paneles
this.pDibujo.add(lienzoComponent.getLienzoTemplate());
Ahora podemos comprobar la incorporación de nuestro componente, sin embargo, pasa algo curioso, cuando pasamos encima del canvas, como este esta posicionado encima del panel pDibujos ya no se están escuchando los eventos del Mouse, tenemos varias opciones para solucionar este conflicto. Por ejemplo podemos pasar el código de los eventos del mouse en el hijo, sin embargo esto requiere una modificación del código que ya hemos implementado, para no realizar esta modificación podemos pasar la escucha de los mismos eventos desde el padre contenedor hacia el componente hijo.
Dentro de la clase LienzoComponent vamos a pedir como parámetro al panelContenedor, al mismo tiempo se lo vamos a pasar como argumento a la clase Template:
public LienzoComponent(JPanel pPadre){
lienzoTemplate = new LienzoTemplate(this, pPadre);
}
Esto implica que una vez se ejemplifique el componente dentro de la clase ConfiguracionesTemplate se debe pasar el panel que lo contiene:
this.lienzoComponent = new LienzoComponent(pDibujo);
Ahora en la clase LienzoTemplate vamos a recibir como parámetro al panelPadre:
public LienzoTemplate(LienzoComponent lienzoComponent, JPanel pPadre){
...
...
}
Vamos a agregar la escucha de cada uno de los eventos del Mouse al componente, para esto llamaremos los métodos correspondientes para la escucha de este tipo de eventos:
// Dentro del constructor
this.addMouseListener();
this.addMouseMotionListener();
this.addMouseWheelListener();
Ahora vamos a obtener los eventos del mouse que esta escuchando actualmente el padre contenedor, esto lo haremos con los métodos:
Correspondientemente:
// Dentro del constructor
this.addMouseListener(pPadre.getMouseListeners());
this.addMouseMotionListener(pPadre.getMouseMotionListeners());
this.addMouseWheelListener(pPadre.getMouseWheelListeners());
Ahora seguramente el editor de código nos este marcando un error y esto es por que los métodos anteriormente usados, no van a retornar un evento especifico sino un arreglo de eventos por cada categoría, ya que un objeto perfectamente podría escuchar a dos eventos tipo MouseListener por dar un ejemplo. Sin embargo sabemos que el panel pDibujo esta escuchando solo un evento de cada tipo asi que en los 3 casos vamos a necesitar el evento ubicado en la posición 0:
// Dentro del constructor
this.addMouseListener(pPadre.getMouseListeners()[0]);
this.addMouseMotionListener(pPadre.getMouseMotionListeners()[0]);
this.addMouseWheelListener(pPadre.getMouseWheelListeners()[0]);
Ahora una vez abramos nuestra aplicación podemos comprobar que efectivamente ahora el canvas también es capaz de escuchar los eventos del mouse que habíamos configurado para el panel contenedor. Nuestro canvas esta listo para usarse, en la siguiente sección vamos a explicar la forma en como pintar diferentes elementos en pantalla.
Vamos a explicar a continuación como pintar una serie de figuras, ademas se explicará una serie de particularidades en los momentos pertinentes.
Vamos a ubicarnos dentro del método paint y vamos a usar el objeto Graphics: g, este objeto tiene una serie de métodos que nos proporcionara herramientas para pintar sobre el canvas. Para pintar un Texto vamos a utilizar el método drawString. Este método recibe varias cosas por parámetro:
@Override
public void paint(Graphics g){
g.drawString("Rectangulos", (this.getWidth() / 2) - 50, 15);
}
Podemos comprobar que se ha pintado este texto dentro del canvas:
Ademas de pintar un texto podemos proporcionar algunos elementos para decorarlo, por ejemplo podemos darle un color y un tipo de fuente, para esto usaremos al servicio sRecursos:
@Override
public void paint(Graphics g){
g.setColor(sRecursos.getColorAzul());
g.setFont(sRecursos.