PintaLlop - Programa de dibujo
Llop Site Home > JAVA > PintaLlop > ArkaLlop
PintaLlop:
Clase PintaLlop package pintallop; import java.io.*; import java.net.*; import javax.imageio.*; import java.awt.*; import java.awt.datatransfer.*; import java.awt.event.*; import java.awt.image.*; import java.awt.print.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.plaf.metal.*; /** Título: PintaLlop Descripción: Prácticas capítulo 11, ejercicio 3 Copyright: Copyright (c) 2005 Empresa: Casa_Llop @author Albert_Lobo @version 1.0 */ /** La clase estrella del programa. Se trata de un applet que puede acceder al portapapeles -una aparente contradicción, por las restricciones de acceso al equipo 'cliente' de los 'applets'. Esto es porque el programa también se puede ejecutar como 'aplicación'. Tenemos 2 configuraciones de ejecución del programa: - Applet: Tiene toda la funcionalidad que permite un applet -no puede guardar imágenes al disco del equipo cliente, ni abrirlas, ni utilizar el portapapeles. - Aplicación: La versión más completa -permite hacer lo que el applet podía y no podía hacer. */ public class PintaLlop extends JApplet implements ClipboardOwner { // Cursores estáticos para los lienzos. /** Cursor con apariencia de lápiz. */ public static Cursor cursorLapiz; /** Cursor con apariencia de goma de borrar. */ public static Cursor cursorGoma; /** Cursor propio del texto. */ public static Cursor cursorTexto; /** Cursor con apariencia de cruz. */ public static Cursor cursorCruz; private JMenuBar barraMenu; // Barra de menú. private JToolBar barraHerramientas; // Barra de herramientas. private PanelPropiedades panelPropiedades; // El panel de propiedades (para la herramienta actual). private JTabbedPane panelLienzo; // El panel para los lienzos. private ColeccionLienzos coleccionLienzos; // Los lienzos. private boolean esAplicacion; // ¿Se ejecuta como aplicación (true), o como applet (false)? private ColeccionHerramientas herramientas; // Las herramientas de dibujo. private Clipboard clipboard; // El portapapeles del sistema. private JTextField cajaURL; // Caja de texto para entrar 'URL's. private short cuentaPestanas; // Cuántos lienzos hay en el 'panelLienzo'. private PanelInformacion panelInfo; // Panel para las instrucciones del programa. // Las acciones que se pueden ejecutar sobre los lienzos. private Action accionNuevoLienzo; private Action accionAbrirImagenDeUrl; private Action accionAbrirImagen; private Action accionGuardarImagen; private Action accionGuardarImagenComo; private Action accionCerrarLienzo; private Action accionImprimirLienzo; private Action accionDeshacer; private Action accionRehacer; private Action accionCopiarImagenAlPortapapeles; private Action accionPegarImagenDelPortapapeles; /** Constructor. Se asume que el programa se ejecutará como 'applet'. */ public PintaLlop () { esAplicacion = false; } private void inicializaTodo () throws Exception { // Gestor de diseño 'BorderLayout'. getContentPane ().setLayout (new BorderLayout ()); // Ningún lienzo en el panel. cuentaPestanas = 0; // Inicializar la caja para entrar 'URL's. cajaURL = new JTextField (); // Inicializar el panel con las instruccones (para el menú 'ayuda'). panelInfo = new PanelInformacion (); // Inicializar las acciones (en la barra de menú). inicializaAcciones (); // Inicializar la barra de menú. barraMenu = creaBarraMenu (); // Inicializar las herramientas, y la barra de herramientas. herramientas = new ColeccionHerramientas (); barraHerramientas = creaBarraHerramientas (); // Inicializar el panel de propiedades de la herramienta actual. panelPropiedades = new PanelPropiedades (herramientas.getHerramientaEnUso ()); // Inicializar el panel para los lienzos, y luego los mismos lienzos. panelLienzo = creaPanelLienzo (); coleccionLienzos = new ColeccionLienzos (herramientas); // Añadimos todos los componentes al 'applet'. setJMenuBar (barraMenu); getContentPane ().add (barraHerramientas, BorderLayout.WEST); getContentPane ().add (panelPropiedades, BorderLayout.SOUTH); getContentPane ().add (panelLienzo, BorderLayout.CENTER); } /** Crea el panel para los lienzos por defecto. @return JTabbedPane El panel para los lienzos. */ private JTabbedPane creaPanelLienzo () { // Es un 'JTabbedPane' que lleva en cada 'tab' o 'pestaña' un lienzo. Cuando cambia el 'tab' // seleccionado, informa a los lienzos de cuál es el nuevo 'protagonista'. // El índice de los lienzos se corresponde con el de los 'tabs'. JTabbedPane retorno = new JTabbedPane (); retorno.addChangeListener (new ChangeListener () { public void stateChanged (ChangeEvent e) { coleccionLienzos.setLienzoActual ((byte) panelLienzo.getSelectedIndex ()); } }); return retorno; } /** El método que inicia 'PintaLlop Aplicación'. Utiliza el 'applet' como un simple 'Component', y lo añade a un 'JFrame'. @param args String [] Argumentos de la línea de comandos. Son obviados. */ public static void main (String args []) { // El 'JFrame' al que se añadirá el applet. // Termina la aplicación al cerrarse. // No puede cambiar de tamaño. JFrame marco = new JFrame ("PintaLlop Aplicación"); marco.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); marco.setResizable (false); marco.setSize (504, 430); // Se coloca en el centro de la pantalla, y se hace visible. Dimension tamanoPantalla = Toolkit.getDefaultToolkit ().getScreenSize (); Dimension tamanoMarco = marco.getSize (); if (tamanoMarco.height > tamanoPantalla.height) tamanoMarco.height = tamanoPantalla.height; if (tamanoMarco.width > tamanoPantalla.width) tamanoMarco.width = tamanoPantalla.width; marco.setLocation ((tamanoPantalla.width - tamanoMarco.width) / 2, (tamanoPantalla.height - tamanoMarco.height) / 2); marco.setVisible (true); // Se inicializa el 'applet'; nótese que se le da acceso al portapapeles. PintaLlop aplicacion = new PintaLlop (); aplicacion.determinaAplicacionOApplet (true); aplicacion.init (); aplicacion.inicializaPortapapeles (); // Se añade el 'applet' al 'marco', se pone el primer lienzo por defecto, y a éste se // le da el 'foco'. marco.getContentPane ().add (aplicacion); aplicacion.nuevoLienzo (); marco.validate (); aplicacion.coleccionLienzos.getLienzoActual ().requestFocus (); } /** Toma el portapapeles del sistema como el propio de 'PintaLlop'. */ private void inicializaPortapapeles () { // Es buena idea asegurarse de que el portapapeles del sistema está accesible. SecurityManager segurata = System.getSecurityManager (); if (segurata != null) try { segurata.checkSystemClipboardAccess (); } catch (SecurityException e) { JOptionPane.showMessageDialog (PintaLlop.this, "No se puede acceder al portapapeles."); return; } clipboard = Toolkit.getDefaultToolkit ().getSystemClipboard (); } /** La función que inicializa 'PintaLlop Applet'. */ public void init () { try { inicializaTodo (); } catch (Exception e) { System.err.println ("Error al iniciar PintaLlop."); } } /** Al iniciar el applet, se crea el primer lienzo por defecto, y se da el 'foco'. */ public void start () { nuevoLienzo (); coleccionLienzos.getLienzoActual ().requestFocus (); } /** Obtener información del applet: el nombre del autor. */ public String getAppletInfo () { return "Autor: Albert Lobo, 2005."; } /** Determina la configuración de ejecución del programa. Para que la función surta efecto, debe llamarse antes de 'inicializarTodo ()'. @param bool boolean 'true' para ejecutar el programa como aplicación, y 'false' para ejecutarlo como a 'applet'. */ private void determinaAplicacionOApplet (boolean bool) { esAplicacion = bool; } /** Inicializa las acciones para tratar los lienzos. */ private void inicializaAcciones () { // Crear un nuevo lienzo para dibujar. accionNuevoLienzo = new AbstractAction ("Nuevo lienzo") { public void actionPerformed (ActionEvent evento) { nuevoLienzo (); } }; // Abrir una imagen en una URL (ejmplo: "es.geocities.com/imagenes/b1.jpg"). accionAbrirImagenDeUrl = new AbstractAction ("Abrir imagen de URL") { public void actionPerformed (ActionEvent evento) { // Abre un 'Dialog' en el que se puede entrar una URL (en 'cajaURL'). Object textoBotones [] = {"Aceptar", "Cancelar"}; int retorno = JOptionPane.showOptionDialog (PintaLlop.this, cajaURL, "Entre la URL donde está la imagen", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, textoBotones, textoBotones [0]); if (retorno == JOptionPane.OK_OPTION) { // Si el usuario acepta, habrá que hacer un par de comprobaciones: // La cadena debe empezar por "http://", y terminar en alguna de las extensiones de imágenes // reconocidas: '.gif', '.jpg', y '.png'. // Para validar más fácilmente la URL, utilizamos la dirección en minúsculas. String cadenaUrl = cajaURL.getText (); String cadenaUrlMinusculas = new String (cadenaUrl).toLowerCase (); if (!cadenaUrlMinusculas.startsWith ("http://")) cadenaUrl = "http://" + cadenaUrl; if (!cadenaUrlMinusculas.endsWith (".png") && !cadenaUrlMinusculas.endsWith (".gif") && !cadenaUrlMinusculas.endsWith (".jpg") && !cadenaUrlMinusculas.endsWith (".jpeg")) { JOptionPane.showMessageDialog (PintaLlop.this, "En la URL entrada no hay una imagen reconocida."); return; } // Sacamos la imagen de la URL. URL url = null; Image i = null; try { url = new URL (cadenaUrl); i = ImageIO.read (url); } catch (MalformedURLException e) { } catch (IOException e) {} if (i == null) { // Si no hay imagen, una de dos: o la URL no existe, o no hay conexión a Internet. JOptionPane.showMessageDialog (PintaLlop.this, "La URL entrada no es válida. " + "Compruebe que está bien escrita."); return; } // Si no hay lienzos abiertos, se crea uno nuevo para pegar la imagen. if (coleccionLienzos.getNumeroLienzos () == -1) nuevoLienzo (); // Pegamos la imagen. coleccionLienzos.getLienzoActual ().pegaImagen (i); } } }; // Abrir una imagen del disco duro. accionAbrirImagen = new AbstractAction ("Abrir imagen") { public void actionPerformed (ActionEvent evento) { // Se abre el 'JFileChooser' personalizado para que el usuario pueda elegir la imagen. SelectorImagenes selector = new SelectorImagenes ("Abrir"); int opcion = selector.showOpenDialog (null); if (opcion == JFileChooser.APPROVE_OPTION) { // Leemos la imagen. Image i = null; try { i = ImageIO.read (selector.getSelectedFile ()); } catch (IOException e) {} if (i == null) { // El archivo está probablemente corrupto. JOptionPane.showMessageDialog (PintaLlop.this, "El archivo no es válido."); return; } // Si no hay lienzos abiertos, se crea uno nuevo para pegar la imagen. if (coleccionLienzos.getNumeroLienzos () == -1) nuevoLienzo (); // Pegamos la imagen. coleccionLienzos.getLienzoActual ().pegaImagen (i); } } }; // Guardar la imagen al disco. accionGuardarImagen = new AbstractAction ("Guardar imagen") { public void actionPerformed (ActionEvent evento) { // Lo primero es comprobar que el lienzo ya se ha guardado en un archivo. // Si no, 'guardamos la imagen como'. if (coleccionLienzos.getLienzoActual ().getArchivo() == null) guardarImagenComo (); else try { ImageIO.write ((RenderedImage)coleccionLienzos.getLienzoActual ().getDibujo (), coleccionLienzos.getLienzoActual ().getExtension (), coleccionLienzos.getLienzoActual ().getArchivo ()); } catch (IOException e) {} } }; // Guardar la imagen al disco en un nuevo archivo. accionGuardarImagenComo = new AbstractAction ("Guardar imagen como") { public void actionPerformed (ActionEvent evento) { guardarImagenComo (); } }; // Imprimir el lienzo. accionImprimirLienzo = new AbstractAction ("Imprimir lienzo") { public void actionPerformed (ActionEvent evento) { // Lo primero es mirar si hay impresora en este equipo. PrinterJob controlImpresion = PrinterJob.getPrinterJob (); if (controlImpresion.lookupPrintServices ().length == 0) { JOptionPane.showMessageDialog (PintaLlop.this, "No hay ninguna impresora disponible."); return; } // Renderizamos el dibujo en el lienzo para que se imprima. // Mostramos el 'Dialog' para cambiar propiedades de la impresión, y si el usuario acepta, imprimimos. controlImpresion.setPrintable (new Impresion ()); if (controlImpresion.printDialog ()) { try { controlImpresion.print (); } catch (PrinterException e) {} } } }; // Cierra el lienzo actualmente en pantalla. accionCerrarLienzo = new AbstractAction ("Cerrar lienzo") { public void actionPerformed (ActionEvent evento) { // Se destruye el liezo, y se quita el 'tab' del 'panelLienzos'. coleccionLienzos.destruyeLienzo (); panelLienzo.remove (coleccionLienzos.getNumeroLienzoActual ()); // Si éste era el último lienzo en pantalla, desactivamos las acciones pertinentes. if (coleccionLienzos.getNumeroLienzos () == -1) desactivaAccionesNoDisponibles (); } }; // Deshacer el último cambio en el lienzo actual. accionDeshacer = new AbstractAction ("Deshacer") { public void actionPerformed (ActionEvent evento) { coleccionLienzos.getLienzoActual ().deshacer (); } }; // Rehacer el último cambio en el lienzo actual. accionRehacer = new AbstractAction ("Rehacer") { public void actionPerformed (ActionEvent evento) { coleccionLienzos.getLienzoActual ().rehacer (); } }; // Copia la imagen en el lienzo actual al portapapeles. accionCopiarImagenAlPortapapeles = new AbstractAction ("Copiar imagen al portapapeles") { public void actionPerformed (ActionEvent evento) { clipboard.setContents (coleccionLienzos.getLienzoActual (), PintaLlop.this); } }; // Pega la imagen del portapapeles al lienzo actual. accionPegarImagenDelPortapapeles = new AbstractAction ("Pegar imagen del portapapeles") { public void actionPerformed (ActionEvent evento) { // En esta interfaz pondremos información sobre los datos a transferir desde el portapapeles // a la aplicación. Transferable imagen = null; try { imagen = clipboard.getContents (null); } catch (IllegalStateException e) { JOptionPane.showMessageDialog (PintaLlop.this, "Portapapeles no accesible. " + "Puede que otro programa lo tenga 'secuestrado'."); return; } // Si había algo en el portapapeles, lo pega como imagen en el lienzo. if (imagen != null) try { coleccionLienzos.getLienzoActual ().pegaImagen ((Image) imagen.getTransferData (DataFlavor.imageFlavor)); } catch (UnsupportedFlavorException e) { } catch (IOException e) {} } }; } /** Desactiva las acciones que no deben estar disponibles cuando no hay lienzos en pantalla. */ private void desactivaAccionesNoDisponibles () { accionGuardarImagen.setEnabled (false); accionGuardarImagenComo.setEnabled (false); accionCerrarLienzo.setEnabled (false); accionImprimirLienzo.setEnabled (false); accionDeshacer.setEnabled (false); accionRehacer.setEnabled (false); accionCopiarImagenAlPortapapeles.setEnabled (false); accionPegarImagenDelPortapapeles.setEnabled (false); } /** Activa las acciones que deben estar disponibles cuando hay algún lienzo en pantalla. */ private void activaAccionesDisponibles () { accionGuardarImagen.setEnabled (true); accionGuardarImagenComo.setEnabled (true); accionCerrarLienzo.setEnabled (true); accionImprimirLienzo.setEnabled (true); accionDeshacer.setEnabled (true); accionRehacer.setEnabled (true); accionCopiarImagenAlPortapapeles.setEnabled (true); accionPegarImagenDelPortapapeles.setEnabled (true); } /** Crea la barra de menú por defecto del programa, le añade los menús 'Archivo' y 'Edición', y la manda de vuelta. @return JMenuBar La barra de menú. */ private JMenuBar creaBarraMenu () { JMenuBar retorno = new JMenuBar (); // Añadimos el menú 'Archivo', y le ponemos los 'items' (en este caso, acciones). // Nótese que según se esté ejecutando 'PintaLlop Aplicación' o 'Applet' // habrá más o menos acciones disponibles. // Hay 'JMenuItems' que tienen 'acelerador' // -una combinación de teclas que ejecuta la acción automáticamente. JMenu archivo = new JMenu ("Archivo"); archivo.add (accionNuevoLienzo).setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_N, KeyEvent.CTRL_MASK)); archivo.add (accionAbrirImagenDeUrl).setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_A, KeyEvent.CTRL_MASK + KeyEvent.ALT_MASK)); if (esAplicacion) { archivo.add (accionAbrirImagen).setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_A, KeyEvent.CTRL_MASK)); archivo.add (accionGuardarImagen).setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_S, KeyEvent.CTRL_MASK)); archivo.add (accionGuardarImagenComo).setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_Z, KeyEvent.CTRL_MASK + KeyEvent.ALT_MASK)); } archivo.add (accionImprimirLienzo).setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_I, KeyEvent.CTRL_MASK)); archivo.add (accionCerrarLienzo).setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_Q, KeyEvent.CTRL_MASK)); // El botón para terminar la aplicación no tiene sentido en un contexto de 'applet'. if (esAplicacion) { archivo.addSeparator (); archivo.add (new AbstractAction ("Salir") { public void actionPerformed (ActionEvent evento) { System.exit (0); } }).setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_F4, KeyEvent.ALT_MASK)); } // Añadimos el menú 'Edición', igual que hemos hecho con el 'Archivo'. JMenu edicion = new JMenu ("Edición"); edicion.add (accionDeshacer).setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_Z, KeyEvent.CTRL_MASK)); edicion.add (accionRehacer).setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_Y, KeyEvent.CTRL_MASK)); if (esAplicacion) { edicion.addSeparator (); edicion.add (accionCopiarImagenAlPortapapeles).setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_C, KeyEvent.CTRL_MASK)); edicion.add (accionPegarImagenDelPortapapeles).setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_V, KeyEvent.CTRL_MASK)); } // Añadimos los 2 menús creados hasta ahora a la 'JMenuBar', y la mandamos de vuelta. retorno.add (archivo); retorno.add (edicion); return retorno; } /** Crea un nuevo lienzo, y lo añade al panel. */ private synchronized void nuevoLienzo () { // Si es el primer lienzo el que se está creando, activamos las acciones. if (coleccionLienzos.getNumeroLienzos () == -1) activaAccionesDisponibles (); // Intentamos crear el nuevo lienzo. if (!coleccionLienzos.creanuevoLienzo ()) return; // Si ha salido bien, se añade al panel de los lienzos. panelLienzo.addTab ("Lienzo " + String.valueOf (++cuentaPestanas), coleccionLienzos.getLienzoFinal ()); coleccionLienzos.setLienzoActual (coleccionLienzos.getNumeroLienzos ()); coleccionLienzos.preparaNuevoLienzo (); panelLienzo.setSelectedIndex (panelLienzo.getTabCount () - 1); } /** Permite guardar la imagen del lienzo actual al disco. Primero, muestra un 'Dialog' en el que se puede elegir el formato de la imagen entre los disponibles: '.jpg' o '.png' -no hay codificadores '.gif' en las librerías estándar. Luego, muestra un 'SelectorImagenes' para especificar dónde se guardará la imagen. */ private void guardarImagenComo () { // Un 'JRadioButton' para cada formato. JRadioButton botonJpg = new JRadioButton ("Formato JPG"); botonJpg.setSelected (true); JRadioButton botonPng = new JRadioButton ("Formato PNG"); // Un grupo de botones para los 'JRadioButton's. ButtonGroup grupoBotones = new ButtonGroup (); grupoBotones.add (botonJpg); grupoBotones.add (botonPng); // Un panel para meter los botones. JPanel panelBotones = new JPanel (); panelBotones.add (botonJpg); panelBotones.add (botonPng); Object textoBotones [] = {"Aceptar", "Cancelar"}; int retorno = JOptionPane.showOptionDialog (PintaLlop.this, panelBotones, "Elija el formato de la imagen", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, textoBotones, textoBotones [0]); // El usuario acaba de decidir el formato de la imagen. if (retorno == JOptionPane.OK_OPTION) { if (botonJpg.isSelected ()) coleccionLienzos.getLienzoActual ().setExtension ("jpg"); else coleccionLienzos.getLienzoActual ().setExtension ("png"); } else return; // Ahora saltará el 'SelectorImagenes'. SelectorImagenes selector = new SelectorImagenes ("Guardar"); int opcion = selector.showOpenDialog (null); if (opcion == JFileChooser.APPROVE_OPTION) { boolean archivoExiste = false; File archivo; String nombreArchivoMinusculas = selector.getSelectedFile ().getName ().toLowerCase (); if (!nombreArchivoMinusculas.endsWith (coleccionLienzos.getLienzoActual ().getExtension ())) archivo = new File (selector.getSelectedFile ().getAbsolutePath () + "." + coleccionLienzos.getLienzoActual ().getExtension ()); else archivo = selector.getSelectedFile (); try { archivoExiste = archivo.createNewFile (); } catch (IOException e) {} // Estamos creando un nuevo archivo, así que no podemos permitir que otro se sobreescriba. if (!archivoExiste) { JOptionPane.showMessageDialog (PintaLlop.this, "Existe otro archivo con este nombre. Cámbielo."); return; } try { ImageIO.write ((RenderedImage) coleccionLienzos.getLienzoActual ().getDibujo (), coleccionLienzos.getLienzoActual ().getExtension (), archivo); } catch (IOException e) { JOptionPane.showMessageDialog (PintaLlop.this, "No se ha podido guardar la imagen."); return; } // Indicamos al lienzo dónde está guardado su archivo. // Si intentamos 'Guardar', la imagen irá directamente al archivo en el disco. coleccionLienzos.getLienzoActual ().setArchivo (archivo); } } /** Tengamos en cuenta cómo funciona la herramienta de texto: Al hacer click sobre el lienzo, se indica dónde irá el texto. A falta de un cursor más sofisticado, cuando no hay texto, se añade una barra vertical ('|') para indicar su posición. Si, con la misma herramienta, se vuelve a hacer click con sobre el lienzo, ese cursor quedará empastado en el lienzo. El solo propósito de esta función es evitar esto. */ private void terminaTexto () { if (herramientas.getHerramientaEnUso ().getTipo () == ColeccionHerramientas.TEXTO) if (herramientas.getHerramientaEnUso ().getCadena ().equals ("|")) { herramientas.getHerramientaEnUso ().setCadena (""); coleccionLienzos.getLienzoActual ().pintaTexto (); } } /** Crea la barra de herramientas por defecto, y la manda de vuelta. De paso, completa la barra de menú añadiendo los menús 'Propiedades' y 'Ayuda'. @return JToolBar La barra de herramientas. */ private JToolBar creaBarraHerramientas () { // Creamos la barra de herramientas. JToolBar retorno = new JToolBar ("Barra de herramientas"); retorno.setLayout (new GridLayout (6, 1)); // Creamos el menú 'Herramientas'. JMenu menuHerramientas = new JMenu ("Herramientas"); // Creamos la acción que pone el 'Lápiz' como la herramienta en uso. // Añadimos acción a la barra de herramientas, y también al menú 'Herramientas'. // Añadiremos con la misma lógica el resto de acciones. Action accion = new AbstractAction ("Lápiz", herramientas.getIcono (ColeccionHerramientas.LAPIZ)) { public void actionPerformed (ActionEvent evento) { terminaTexto (); herramientas.setHerramientaEnUso (ColeccionHerramientas.LAPIZ); panelPropiedades.setHerramientaEnUso (herramientas.getHerramientaEnUso ()); } }; retorno.add (accion); menuHerramientas.add (accion); accion = new AbstractAction ("Goma", herramientas.getIcono (ColeccionHerramientas.GOMA)) { public void actionPerformed (ActionEvent evento) { terminaTexto (); herramientas.setHerramientaEnUso (ColeccionHerramientas.GOMA); panelPropiedades.setHerramientaEnUso (herramientas.getHerramientaEnUso ()); } }; retorno.add (accion); menuHerramientas.add (accion); accion = new AbstractAction ("Línea", herramientas.getIcono (ColeccionHerramientas.LINEA)) { public void actionPerformed (ActionEvent evento) { terminaTexto (); herramientas.setHerramientaEnUso (ColeccionHerramientas.LINEA); panelPropiedades.setHerramientaEnUso (herramientas.getHerramientaEnUso ()); } }; retorno.add (accion); menuHerramientas.add (accion); accion = new AbstractAction ("Rectángulo", herramientas.getIcono (ColeccionHerramientas.RECTANGULO)) { public void actionPerformed (ActionEvent evento) { terminaTexto (); herramientas.setHerramientaEnUso (ColeccionHerramientas.RECTANGULO); panelPropiedades.setHerramientaEnUso (herramientas.getHerramientaEnUso ()); } }; retorno.add (accion); menuHerramientas.add (accion); accion = new AbstractAction ("Óvalo", herramientas.getIcono (ColeccionHerramientas.OVALO)) { public void actionPerformed (ActionEvent evento) { terminaTexto (); herramientas.setHerramientaEnUso (ColeccionHerramientas.OVALO); panelPropiedades.setHerramientaEnUso (herramientas.getHerramientaEnUso ()); } }; retorno.add (accion); menuHerramientas.add (accion); accion = new AbstractAction ("Texto", herramientas.getIcono (ColeccionHerramientas.TEXTO)) { public void actionPerformed (ActionEvent evento) { herramientas.setHerramientaEnUso (ColeccionHerramientas.TEXTO); panelPropiedades.setHerramientaEnUso (herramientas.getHerramientaEnUso ()); } }; retorno.add (accion); menuHerramientas.add (accion); // El resto de función crea el menú 'Ayuda' para la barra de menú. JMenu ayuda = new JMenu ("Ayuda"); // Esta acción hace saltar una ventana con las instrucciones de uso de 'PintaLlop'. ayuda.add (new AbstractAction ("Introducción a PintaLlop") { public void actionPerformed (ActionEvent evento) { String textoBotones [] = new String [] {"Aceptar"}; JOptionPane.showOptionDialog (PintaLlop.this, panelInfo, "Introducción a PintaLlop", JOptionPane.OK_OPTION, JOptionPane.PLAIN_MESSAGE, null, textoBotones, textoBotones [0]); } }); ayuda.addSeparator (); // Esta acción hace saltar una ventana con información sobre la versión y el autor de 'PintaLlop'. ayuda.add (new AbstractAction ("Acerca de PintaLlop " + (esAplicacion ? "Aplicación" : "Applet")) { public void actionPerformed (ActionEvent evento) { String mensajeAcerca = "<HTML>PintaLlop "; mensajeAcerca += esAplicacion ? "Aplicación versión 1.0" : "Applet versión 1.0"; mensajeAcerca += "<BR>Copyright (c) 2005, Albert Lobo"; JLabel etiqueta = new JLabel (mensajeAcerca); etiqueta.setHorizontalAlignment (JLabel.CENTER); String textoBotones [] = new String [] {"Aceptar"}; JOptionPane.showOptionDialog (PintaLlop.this, etiqueta, "Acerca de PintaLlop " + (esAplicacion ? "Aplicación" : "Applet"), JOptionPane.OK_OPTION, JOptionPane.PLAIN_MESSAGE, null, textoBotones, textoBotones [0]); } }); // Añadimos los dos menús acabados de crear a la barra de menú. barraMenu.add (menuHerramientas); barraMenu.add (ayuda); // La barra de herramientas se envía de vuelta. // ¿Por qué inicializar los otros 2 menús de la 'JMenuBar' aquí? // Como tanto la barra de herramientas como la de menú deben tener acceso a las mismas acciones // para cambiar de herramienta, las inicializamos en la misma función. // El menú 'Ayuda', lógicamente, es el último a añadir a la barra de menú. return retorno; } /** Notifica al applet que ha perdido la posesión del portapapeles. No utilizamos ninguno de los argumentos. @param nuevoPortapapeles Clipboard El portapapeles. @param transferible Transferable Datos que este programa ha puesto en el portapapeles. */ public void lostOwnership (Clipboard nuevoPortapapeles, Transferable transferible) { JOptionPane.showMessageDialog (PintaLlop.this, "El applet ha perdido la posesión del portapapeles."); } /** Método estático que proporciona un icono, construido a partir de una imagen del fichero de recursos del programa. @param imagen String Nombre de la imagen para el icono. @return ImageIcon El icono con la imagen especificada. */ public static ImageIcon getIcono (String imagen) { URL uRL = PintaLlop.class.getResource ("rcsPintaLlop/" + imagen) ; if (uRL == null) { System.err.println (imagen + " no encontrada."); return null; } return new ImageIcon (uRL); } /** Inicializar las variables estáticas: Define el 'look'n'feel' del programa, e inicializa los cursores para los lienzos. */ static { try { UIManager.setLookAndFeel (new MetalLookAndFeel ()); } catch (Exception e) {} cursorLapiz = Toolkit.getDefaultToolkit ().createCustomCursor (PintaLlop.getIcono ("cursorLapiz.gif").getImage (), new Point (4, 28), "CursorLápiz"); cursorGoma = Toolkit.getDefaultToolkit ().createCustomCursor (PintaLlop.getIcono ("cursorGoma.gif").getImage (), new Point (2, 25), "CursorGoma"); cursorTexto = new Cursor (Cursor.TEXT_CURSOR); cursorCruz = new Cursor (Cursor.CROSSHAIR_CURSOR); } /** Interfaz que se encarga de imprimir. */ class Impresion implements Printable { /** Imprime la imagen en el lienzo actual. Cuando se llama a la función 'print ()' de 'PrintJob', ésta a su vez llama al 'print ()' de esta interfaz, 'Printable'. @param graficos Graphics Contexto 'Graphics' sobre el que se dibuja la imagen. @param formatoPagina PageFormat El tamaño y la orientación de la página a imprimir. @param indicePagina int Índice de la página que se imprimirá. @throws PrinterException Excepción lanzada al terminar la impresión. @return int 'Printable.PAGE_EXISTS' -asumimos que, llegado este punto, la imagen a imprimir se renderizará siempre. */ public int print (Graphics graficos, PageFormat formatoPagina, int indicePagina) throws PrinterException { // Para que no se líe a imprimir infinitas páginas, indicamos que después de la primera // página ya no necesita imprimir más. if (indicePagina >= 1) return Printable.NO_SUCH_PAGE; graficos.drawImage (coleccionLienzos.getLienzoActual ().getDibujo (), (int) formatoPagina.getImageableX (), (int) formatoPagina.getImageableY (), null); return Printable.PAGE_EXISTS; } } /** Clase interna que extiende 'JScrollPane'. Lleva un 'JEditorPane' en el que incrustamos una página HTML con información acerca del programa. */ class PanelInformacion extends JScrollPane { // Panel en el que pegaremos el archivo HTML. private JEditorPane pnlEdtr; /** Constructor. */ public PanelInformacion () { // Llamada al constructor de la superclase. La barra deslizante debe ser vertical. super (); setPreferredSize (new Dimension (600, 400)); setVerticalScrollBarPolicy (JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); // Inicializa 'pnlEdtr', se hace no editable, y se incrusta la página web. pnlEdtr = new JEditorPane (); pnlEdtr.setEditable (false); try { pnlEdtr.setPage (PintaLlop.class.getResource ("rcsPintaLlop/info.htm")); } catch (IOException e) {} setViewportView (pnlEdtr); } } }
¿Comentarios, sugerencias?: llopsite.at.yahoo.es | © 2005-07 Albert Lobo
Última actualización: 18-Feb-2007