Programación Avanzada para Internet Práctica 2 (2 sesiones) Carlos García Miragall y Javier Piris ÍNDICE 1.- Introducción 2.- Estructura de la aplicación y las clases. 3.- Actividades 4.- Ampliaciones. 5.- Bibliografía. OBJETIVOS Aprender a diseñar una interfaz gráfica de usuario conectándola con las clases del resto de una aplicación. Aprender a diseñar una interfaz gráfica de usuario como una extensión de un JFrame. 1.- Introducción En esta práctica se pretende desarrollar los aspectos más básicos de la interfaz de usuario y la lógica de un programa para la edición gráfica de figuras geométricas. Visualmente el editor debe tener el siguiente aspecto: 2.- Estructura de la aplicación y las clases El desarrollo de la aplicación se descompone en dos partes diferenciadas: Diseño de las clases relacionadas con el manejo de figuras geométricas. 1 Diseño de la interfaz gráfica Diseño de las clases relacionadas con el manejo de figuras geométricas Para el tratamiento del dibujo se van a utilizar las clases predefinidas de la API de Java, pertenecientes a la librería java.awt.geom. Se trata de una librería donde están definidas las herramientas para el manejo de dibujos en 2D. Existen varias clases para manipular la geometría: Clases que implementan la interfaz Shape (figura) y la clase Area que proporciona mecanismos para añadir, quitar o intersectar figuras geométricas. La interfaz principal de la librería es la Shape, donde las clases que la implementan representan las figuras geométricas más habituales que utilizaremos para realizar los dibujos: La clase abstracta Elipse2D, que representa una elipse. Tiene dos clases estáticas anidadas: Elipse2D.Double y Elipse2D.Float, dependiendo de la precisión requerida. La clase abstracta Line2D, que representa un segmento de recta. Tiene dos clases estáticas anidadas: Line2D.Double y Line2D.Float, dependiendo de la precisión requerida. La clase abstracta Rectangle2D, que representa un rectángulo. Tiene dos clases estáticas anidadas: Rectangle2D.Double y Rectangle2D.Float. Point2D, que representa un punto. Tiene dos clases estáticas anidadas: Point2D.Double y Point2D.Float. Como ejercicio se propone consultar la documentación de Java y visitar dichas clases, tratando de entender cómo se crean y cuales son las operaciones básicas de manipulación. Por otro lado, la aplicación maneja el concepto de Dibujo, debido a que se necesita abrir, editar, guardar un dibujo, etc ... Por lo tanto tendremos que definir la clase Dibujo formada por una lista de Figuras, un color o imagen de fondo, unas dimensiones del lienzo etc... public class Dibujo { Color fondo; LinkedList Figuras; ... public void dibujar(Graphics2D g) {...} } Para definir la lista de figuraras podéis utilizar la lista con posición distinguida estudiada en la asignatura EDA o bien como también se estudió en dicha asignatura cualquiera de las implementaciones de la lista que aparece en al API de Java. En la librería java.util, tenéis las clases LinkedList, ArrayList y Vector que implementan una lista. La clase dibujo además de otros métodos que creáis oportunos tendrá que tener un método dibujar que dibuje las figuras geométricas sobre el objeto gráfico que se le pasa 2 como referencia. Para dibujar una figura, objeto de la clases Shape, en un objeto grafico (Graphics2D) sólo tendremos que invocar al método draw. Por lo tanto, a no ser que se decida utilizar la clase que implementa una lista vista en la asignatura EDA, en esta parte lo único que tenemos que hacer es estudiar las clases de la API de Java e implementar la clase Dibujo. Diseño de la interfaz gráfica A continuación se describe una descomposición de clases e interfaces para el diseño de la interfaz gráfica de la aplicación: Clase Igu. En esta clase se deben incluir los elementos principales de la interfaz, estos son: las componentes compuestas Barra_Botones, Barra_Estado, Barra_Menu y el Area_Trabajo. Cada una de estas componentes compuestas esta formada por otras componentes más básicas Clase Contexto. Clase en la que se definen los atributos que deben ser accedidos por toda la aplicación. Todos los atributos son estáticas. Clase Area_trabajo. Esta clase es una extensión de una JPanel, y representa la zona de dibujo. En su versión más simplificada contiene un único dibujo pero más adelante se extenderá para que puedan estar editándose varios dibujos simultáneamente. Clase Barra_Estado. Esta clase representa la barra inferior de las aplicaciones en las que se informa al usuario de las acciones que se están realizando en la aplicación. Es una extensión de un JPanel y en su versión más sencilla sólo tiene un JLabel y un método para presentar frases. Clase Barra_Botones. Esta clase es una extensión de un JToolBar, que contiene el juego de botones de figuras, color de realce, relleno etc. Clase Barra_Menu. Esta clase es una extensión de un JMenuBar, en la que se definen los aspectos relacionados con el menú. Se incorporan los elementos del menú y los oyentes correspondientes. Clase Principal para lanzar a ejecución la aplicación. En un proyecto Bluej para la igu, el desglose quedaría de la siguiente forma: 3 La estructura básica de cada una de las clases será la siguiente: La clase Igu. /** * class Igu extiende de JFrame y es la clase principal de la igu. * */ public class Igu extends JFrame { // representa el menu de la aplicación public Barra_Menu bm; // La barra lateral tiene el juego de botones de las figuras // y de los colores public Barra_Botones bb; // Un atributo static de esta clase se encuentre en la // clase Contexto public Barra_Estado be; // clase lienzo, idem que la anterior public Area_Trabajo at; public Igu(String nombre) { // El nombre que le pasemos como parámetro será el // el nombre que aparezca en la ventana del editor super(nombre); // Obtenemos el marco de trabajo Container cp= getContentPane(); // el gestionador de diseño es el BorderLayout cp.setLayout(new BorderLayout()); // area de trabajo para para dibujar at= new Area_Trabajo(); cp.add("Center",at); // Añadimos la barra que contiene el juego de // botones de las figuras y los colores bb= new Barra_Botones(); cp.add("West",bb); // Al final en el sur ponemos la barra de estado 4 be=new Barra_Estado(); cp.add("South", be); // creamos y añadimos al Frame la barra de menu bm=new Barra_Menu(); setJMenuBar(bm);} // Con la finalidad de poder acceder a cada una de las .... } La clase Principal. Clase que se utiliza para lanzar a ejecución la aplicación. /** * clase Principal lanza a ejecución toda la aplicación. * */ public class Principal { /** * Método principal de la aplicación */ public static void main (String arg[]) {JFrame.setDefaultLookAndFeelDecorated(true); // creamos una instancia de la clase Igu Igu interfaz=new Igu("editor gráfico"); // El marco principal lo guardamos en la clase contexto Contexto.interfaz=interfaz; // Incrementamos su tamaño, por defecto es 0,0 interfaz.setSize(500,500); // La hacemos visible interfaz.setVisible(true); } } La clase Contexto. En esta clase sólo se definen atributos estáticos que contienen información visible por todos los elementos de la aplicación. Existen dos atributos básicos que deben estar referenciados en esta clase: el marco principal de la aplicación, a partir del cual se puede acceder a los demás componentes de la interfaz, y el dibujo que se está editando actualmente. Se recuerda que la forma de acceder a los atributos estáticos de una clase consiste en indicar el nombre de la clase y después el atributo. A continuación se aparecen algunos de los atributos. /** * Clase que contiene atributos static comunes a toda la aplicación. * */ public class Contexto { static Dibujo dib; 5 // Atributo que representa el dibujo actual static Igu interfaz; // Indica el tipo de figura que se está dibujando static int figura; ... } La clase Area_Trabajo. La clase Area_Trabajo es una de las clases principales de la aplicación. Es la componente fundamental con la que interactuará el usuario, dibujando con el ratón las figuras. En esta clase se controlan los eventos de ratón y por ello por ello va requerir mayor atención. En la estructura que se presenta a continuación se comentan los aspectos esenciales de esta clase. /** * Clase que representa un lienzo para dibujar. * */ public class Area_Trabajo extends JPanel{ // Constructor de la clase public Area_Trabajo (){ setBackground(Color.gray); OYENTE oy1= new OYENTE(); // debido a la complejidad y versatilidad de los oyentes de // de ratón existen dos interfaces sobre el MouseEvent addMouseListener(oy1); addMouseMotionListener(oy1); } // Hay que reescribir el método paintComponent de // forma que cada vez que se tiene que repintar el editor // se invoca este método, public void paintComponent (Graphics g){ // se debe de dibujar el dibujo que se esta editando // Recuperar el dibujo Dibujo dib=Contexto.dibujo; // ejecutamos el método dibujar pasándole la información //correspondiente dib.dibujar(g) ... ;} class OYENTE extends MouseAdapter implements MouseListener, MouseMotionListener{ // Apretamos el botón del ratón public void mousePressed( MouseEvent e){ } // Soltamos el botón del ratón public void mouseReleased(MouseEvent e){ .... } public void mouseMoved ( MouseEvent e){;} 6 // Mientras todavía no hemos levantado el botón del // ratón y estamos decidiendo el tamaño de la figura // Este código se comentará en clase public void mouseDragged( MouseEvent e){ ....}}} La clase Barra_Estado. La clase Barra_Estado es una extensión de la clase JPanel. Es igual a la utilizada en el problema de la calculadora. La clase Barra_Botones. La clase Barra_Botones es una extensión de la clase JPanel. Esta clase se utiliza para distribuir correctamente los diferentes juegos de botones. /** * En esta clase están los botones * de las figuras y del color * */ public class Barra_Botones extends JPanel { ButtonGroup juego[]; public Barra_Botones() { }} La clase Barra_Menu. La clase Barra_Menu es una extensión de la clase MenuBar. Sobre esta clase se va a construir el menu de la aplicación. En esta práctica únicamente se pretende que se coloque sin darle funcionalidad. public class Barra_Menu extends JMenuBar { // Los elementos principales de la barrra de menu JMenu m1,m2,m3; JMenuItem nuevo, abrir, guardar; JMenuItem guardarcomo, copiar, cortar, pegar; public Barra_Menu () { .......}} // Elementos del menu m1 = new JMenu("Ficheros"); m2 = new JMenu("Edición") 3.- Actividades Implementar en Java todas las clases presentadas en el apartado anterior. Las cuestiones que no se han desarrollado en el apartado anterior serán comentadas en la clase de prácticas. 4.- Ampliaciones 7 Se comentarán en clase de prácticas. 5.- Bibliografía Bruce Eckel. “ Piensa en Java”. Prentice may. 2000 M.A. Weiss .“Estructuras de Datos en JAVA”.. Addison-Wesley. K. Walrath et all.“The JFC Swing Tutorial”. Ed. Addison-Wesley 2004. Documentación de Java 1.4. 8