Prof. Dr. Eric Jeltsch F. Programación en Java2 Tema: MasMenu Lección 12. Extra Menus..., pero con Gui En las secciones GUI(Swing), Events y Layout que se dieron en las lecturas anteriores, se trataron los pasos preliminares y otras herramientas un tanto más sofisticadas para entender la filosofía que estaba detrás de las apariencias gráficas. La idea en este Capítulo es continuar mostrando otras herramientas que ofrece Java2 respecto al diseño de una interfaz de usuario, en este mismo contexto queremos mostrar el dialogo File, como una forma de habilitar los servicios de abrir, cerrar o guardar archivos según o con una cierta extensión. En esta sección se continua con una taraea que había quedado inconclusa y que retomamos con el fin de activar algunos eventos. Dialogo con File Cuando Ud. escribe un applet, no puede acceder archivos sobre la máquina remota, sin embargo para cuando escribe una aplicación podrá abrir o salvar algún tipo de archivo. Java con Swing proporciona la clase apropiada, llamada JFileChooser, la que despliega un cuadro de dialogo como el que se describe a continuación. Notar que JFileChooser no es una subclase de JDialog. Algunas etapas estructuradas para usar JFileChooser y sus propiedades. • Crear un objeto JFileChooser, por ejemplo JFileChooser d= new JFileChooser(); • Setear el directorio llamando el método setCurrentDirectory, por ejemplo d.setCurrentDirectory(new File(“.”); para usar el directorio actual. 1 Ingeniería en Computación , Universidad de La Serena Prof. Dr. Eric Jeltsch F. Programación en Java2 Tema: MasMenu • Si Ud. desea un nombre de archivo por defecto que Ud. espera para escoger hágalo con por ejemplo, d.setSelectedFile(new File(filenombre); • Para habilitar al usuario para seleccionar archivos multiples en el dialogo, hágalo por ejemplo, d.setMultiSelectionEnabled(true); • Si Ud. desea restringir el despliege de los archivos a algunos en particular, por ejemplo para aquellos que tengan la extensión .gif , entonces necesitará herramientas de la interface Filefilter. • Mostrar el box de diálogo llamando a los métodos showOpenDialog o showSaveDialog, por ejemplo, int result = d.showOpenDialog(otra) o int result = d.showSaveDialog(otra).Esta llamada no entrega nada hasta que el usuario ha aceptado un archivo o cancelado el box de dialogo. El valor de retorno es JFileChooser.APROVE_OPTION o JFileChooser.CANCEL_OPTION. • Si Ud. desea seleccionar un archivo o archivos lo podrá hacer con los métodos getSelectedFile(), o getSelectedFiles() resp. Estos métodos entregan ya sea un objeto File simple o un array de objetos File. Si Ud. necesita justamente el nombre de un archivo en particular, hágalo con el método getName(). Por ejemplo, String filenombre= d.getSelectedFile().getName(); Una de las grandes dificultades radica para cuando desee especificar un subconjunto de archivos de los cuales el usuario quisiera escoger. Por ejemplo, supongamos que Ud. quiere escoger un archivo de imagen GIF, entonces desplegara los archivos con extensión .gif. Pero la situación puede ser más compleja, y esto surge para cuando el usuario quiera escoger un archivo JPEG, de donde la extensión es ya sea .jpg o .jpeg. En todo caso para superar este tipo de dificultades se obtiene un solución bien elegante, restringiendo los archivos, y esto lo logra implementando la interface javax.swing.filechooser.FileFilter. Esto significa que el archivo escogido pasa todos los archivos al filtro de archivo y desplegara solo los archivos que el filtro de archivo acepta. Ahora esto es relativamente sencillo escribir sus propios archivos filtrados, para ello deberá implementar los dos métodos de la interface FileFilter. Por ejemplo, public boolean accept(File f); public String getDescription(); el primer método testea si el archivo sera aceptado, mientras que el segundo retorna la descripción del archivo que puede ser desplegado en el archivo escogido de dialogo. Por ejemplo volviéndo a los archivos .gif, podemos usar, public class GifFiltro extends FileFilter{ public boolean accept(File f){ return f.getName().toLowerCase().endsWith(“.gif) f.isDirectory(); } public String getDescription(){ return “GIF Image”; } } || Una buena idea para cuando un usuario de su programa desee o necesite seleccionar un archivo con una extensión no estandar bastara, por ejemplo, 2 Ingeniería en Computación , Universidad de La Serena Prof. Dr. Eric Jeltsch F. Programación en Java2 Tema: MasMenu d.addChoosableFileFilter(d.getAcceptAllFileFilter()); Finalmente, Ud. podrá a los archivos escogidos dotarlos de un distintivo, como por ejemplo un icono especial, la descripción para todos los archivos desplegados. Para hacer esto deberá proporcionar un objeto de una clase extendiendo la clase FileView en el paquete javax.swing.filechooser. Ahora si Ud. desea desplegar diferentes iconos para tipos especiales de archivo, podrá entonces instalar su propio archivo view. Para tal efecto deberá extender la clase FileView e implementar los 5 métodos, getIcon(), getName(), getDescription(), getTypeDescription() y isTraversable(). Por ejemplo, class CafeAmaretto extends javax.swing.filechooser.FileView { public Icon getIcon(File f) { if (f.getName().toLowerCase().endsWith(“.java)) return new ImageIcon(“cafeA.gif”); else return null; } } public String getDescription(File f) { return null; } public String getName(File f) { return null; } public String getTypeDescrition(File f) { return null; } public Boolean isTraversable(File f) { return null; } Ud. deberá instalar este archivo “view” en su file escogido con el método setFileView(), por ejemplo, chooser.setFileView(new CafeAmaretto()); Finalmente, Ud. podrá encontrar más información en la clase ExampleFileView en la demo /jfc/FileChooserDemo de la distribución JDK. Las API’s importantes están en javax.swing.JFileChooser javax.swing.filechooser.FileFilter javax.swing.filechooser.FileView En el siguiente programa verá más sobre el particular. import import import import import javax.swing.*; javax.swing.border.*; java.awt.*; java.awt.event.*; java.io.*; 3 Ingeniería en Computación , Universidad de La Serena Prof. Dr. Eric Jeltsch F. Programación en Java2 Tema: MasMenu // 1. El frame de la clase TJFileChooser . public class TJFileChooser extends JFrame { JMenuItem abrirMI, salveMI, salveComoMI, salirMI; JFileChooser miFileChooser; Container miContainer; JLabel miLabel; File miFile, miSelecFile; public TJFileChooser() { // 2. Para cerrar el frame. this.addWindowListener(new FrameCierre()); // 3. Como tratar el frame sobre el pane. miContainer = this.getContentPane(); // 4. Crea un label y lo agrega al container. miLabel = new JLabel(); miContainer.add(miLabel); // 5. Crea y agrega la barra de menu. JMenuBar miMenuBar = new JMenuBar(); miMenuBar.setBorder(BorderFactory.createEtchedBorder()); miContainer.add(miMenuBar, BorderLayout.NORTH); // 6. Crea y agrega el archivo menu y sus items. JMenu miFileMenu = new JMenu("Archivo"); miMenuBar.add(miFileMenu); JMenuItem miNuevoMI = new JMenuItem("Nuevo"); miNuevoMI.setEnabled(false); miFileMenu.add(miNuevoMI); abrirMI = new JMenuItem("Abrir"); abrirMI.addActionListener(new MIActionListener()); miFileMenu.add(abrirMI); miFileMenu.addSeparator(); salveMI = new JMenuItem("Salve"); salveMI.setEnabled(false); miFileMenu.add(salveMI); salveComoMI = new JMenuItem("Salve Como"); salveComoMI.addActionListener(new MIActionListener()); miFileMenu.add(salveComoMI); miFileMenu.addSeparator(); miFileMenu.addSeparator(); // 7. "Salir" menu item con un action listener. salirMI = new JMenuItem("Salir"); salirMI.addActionListener(new MIActionListener()); miFileMenu.add(salirMI); } // 8. Crea y agrega el menu Edit. JMenu miEditMenu = new JMenu("Editar"); miMenuBar.add(miEditMenu); // 9. Menu action listener. class MIActionListener implements ActionListener { 4 Ingeniería en Computación , Universidad de La Serena Prof. Dr. Eric Jeltsch F. Programación en Java2 Tema: MasMenu public void actionPerformed(ActionEvent ae) { JMenuItem miMenuItem = (JMenuItem) ae.getSource(); // 10. Si el item menu Abrir es seleccionado. if (miMenuItem == abrirMI) { if (miFile == null) { // Crea un archivo que apunta al home directory miFileChooser = new JFileChooser(); } else { // Crea un archivo que apunta al camino del archivo especifico miFileChooser = new JFileChooser(miFile); } /* Show el box de dialogo (returns la opcion seleccionada). la otra opción es showSaveDialog*/ int miSelec = miFileChooser.showOpenDialog(miContainer); //11. Si el boton Abrir es presionado sobre archivo escogido. if (miSelec == JFileChooser.APPROVE_OPTION) { // Se obtiene el archivo seleccionado miFile = miFileChooser.getSelectedFile(); // Display el nombre del archivo en el frame. miLabel.setText("Ud. ha seleccionado el archivo:"+ miFile.getName()); miLabel.setHorizontalAlignment(JLabel.CENTER); return; } // 12. Si el boton Cancelar es pulsado. else if (miSelec == miFileChooser.CANCEL_OPTION) { miLabel.setText("Ud. no ha seleccionado ningún archivo para abrir!"); miLabel.setHorizontalAlignment(JLabel.CENTER); return; } } // 13. Si el item Salvar del menu es pulsado. else if (miMenuItem == salveComoMI) { // Aqui se realiza el salvado del archivo... miFileChooser = new JFileChooser(); int miSelec = miFileChooser.showSaveDialog(miContainer); /*si Ud. tiene un nombre de archivo por defecto, que espera usar, realicelo con el método setSelectedFile*/ miSelecFile = new File("SINTITULO"); miFileChooser.setSelectedFile(miSelecFile); if (miSelec == JFileChooser.APPROVE_OPTION) { // Obtener el archivo seleccionado //miSelecFile = miFileChooser.getSelectedFile(); // Display el nombre del archivo seleccionado en el frame. miLabel.setText("Ud. ha seleccionado el archivo:"+ miFile.getName()); miLabel.setHorizontalAlignment(JLabel.CENTER); return; } else if (miSelec == miFileChooser.CANCEL_OPTION) { 5 Ingeniería en Computación , Universidad de La Serena Prof. Dr. Eric Jeltsch F. Programación en Java2 Tema: MasMenu miLabel.setText("Ud. no ha seleccionado ningun archivo para abrir!"); miLabel.setHorizontalAlignment(JLabel.CENTER); return; } } } } else if (miMenuItem == salirMI) { System.exit(0); } // 14. Listener para cerrar el frame. class FrameCierre extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } } // 15. El metodo principal. public static void main(String[] args) { TJFileChooser miFrame = new TJFileChooser(); miFrame.setTitle("Usos de JFileChooser"); miFrame.setSize(450, 300); miFrame.setVisible(true); } 6 Ingeniería en Computación , Universidad de La Serena Prof. Dr. Eric Jeltsch F. Programación en Java2 Tema: MasMenu Filtrar Archivos import javax.swing.*; import javax.swing.border.*; 7 Ingeniería en Computación , Universidad de La Serena Prof. Dr. Eric Jeltsch F. Programación en Java2 Tema: MasMenu import java.awt.*; import java.awt.event.*; import java.io.*; public class TFiltroFile extends JFrame { JMenuItem openMI, exitMI; JFileChooser fileChooser; Container miContainer; JLabel label; File file, selecFile; public TFiltroFile() { // 1. Para cerrar el frame. this.addWindowListener(new FrameCierre()); // 2. Extraer el trato sobre el frame's content pane. miContainer = this.getContentPane(); // 3. crea un label y lo agrega al container. label = new JLabel(); miContainer.add(label); // 4. Crea y agrega un menu bar. JMenuBar menuBar = new JMenuBar(); menuBar.setBorder(BorderFactory.createEtchedBorder()); miContainer.add(menuBar, BorderLayout.NORTH); // 5. Crea y agrega el menu file y sus menu items, con separador. JMenu fileMenu = new JMenu("File"); menuBar.add(fileMenu); openMI = new JMenuItem("Open"); openMI.addActionListener(new MIActionListener()); fileMenu.add(openMI); fileMenu.addSeparator(); } // 6. "Exit" menu item con una action listener. exitMI = new JMenuItem("Exit"); exitMI.addActionListener(new MIActionListener()); fileMenu.add(exitMI); // 7. Menu action listener. class MIActionListener implements ActionListener { public void actionPerformed(ActionEvent ae) { JMenuItem menuItem = (JMenuItem) ae.getSource(); // 8. Si "Open" menu item es seleccionado if (menuItem == openMI) { if (file == null) { // Crea un archivo apuntando al home directory. fileChooser = new JFileChooser(); } else { // Crea archivo apuntando al archivo especificado en el camino. fileChooser = new JFileChooser(file); } // 9. Agrega un file filter (objeto de MiFileFilter). fileChooser.addChoosableFileFilter(new MiFileFilter()); 8 Ingeniería en Computación , Universidad de La Serena Prof. Dr. Eric Jeltsch F. Programación en Java2 Tema: MasMenu // La siguiente declaracion asignara el nuevo archivo // descartando los otros archivos. fileChooser.setFileFilter(new MiFileFilter()); // 10. Setea el "custom view" para archivos(usando objetos de MiFileView). fileChooser.setFileView(new MiFileView()); // 11. Muestra el dialogo box (returns la opcion seleccionada). int selec = fileChooser.showOpenDialog(miContainer); // 12. Si el boton Open sobre el archivo escogido es pulsado. if (selec == JFileChooser.APPROVE_OPTION) { // Obtiene el archivo seleccionado file = fileChooser.getSelectedFile(); // Display the file name in the frame. label.setText("Ud. ha seleccionado para abrir:"+ file.getName()); label.setHorizontalAlignment(JLabel.CENTER); return; } // 13. Si el boton Cancel es pulsado. else if (selec == fileChooser.CANCEL_OPTION) { label.setText("Ud. no ha seleccionado ningún archivo para abrir!"); label.setHorizontalAlignment(JLabel.CENTER); return; } } // 14. Si el boton Exit es pulsado. else if (menuItem == exitMI) { System.exit(0); } } } } // 15. Listener para cerrar el frame. class FrameCierre extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } // 16. El metodo main. public static void main(String[] args) { TFiltroFile frame = new TFiltroFile(); frame.setTitle("Demo de Filtro de Archivos"); frame.setSize(450, 300); frame.setVisible(true); } // 17. Define una clase de file filter. class MiFileFilter extends javax.swing.filechooser.FileFilter { public boolean accept(File file) { if (file.isDirectory()) { // Aceptar si el archivo miembro del sistema es un directorio return true; } // Recupera el nombre del archivo. String fileNombre = file.getName(); // Note el indice de '.' en el nombre del archivo. int periodIndex = fileNombre.lastIndexOf('.'); 9 Ingeniería en Computación , Universidad de La Serena Prof. Dr. Eric Jeltsch F. Programación en Java2 Tema: MasMenu // Estado de aceptación. boolean accept = false; if (periodIndex>0 && periodIndex<fileNombre.length()-1) { String extension = fileNombre.substring(periodIndex+1).toLowerCase(); if (extension.equals("java")) // Chequea si la extension es ".java" accept = true; else if(extension.equals("html")) // Chequea si la extension es .html. accept = true; } return accept; } // Recupera la descripcion del archivo. public String getDescription() { return "Archivos Java y HTML(*.java, *.html))"; } } // 18. la clase que los visualiza. class MiFileView extends javax.swing.filechooser.FileView { // Define los objetos icon requeridos. ImageIcon javaIcon = new ImageIcon("javaIcon.gif"); ImageIcon htmlIcon = new ImageIcon("htmlIcon.gif"); // Recupera el nombre del archivo. public String getName(File f) { return null; // L&F FileView encontrara esto a la salida de usar // return f.getName(); } // Recupera la descripcion del archivo. public String getDescription(File f) { return null; // L&F FileView encontrara esta salida } // Returns el tipo de archivos, como Java. public String getTypeDescription(File f) { String extension = getExtension(f); String tipo = null; if(extension != null) { if(extension.equals("java")) { tipo = "Archivo Java"; } if(extension.equals("gif")){ tipo = "Archivo Html"; } } return tipo; } // Recupera el icono relevante para el archivo view. public Icon getIcon(File f) { String extension = getExtension(f); Icon icon = null; if (extension != null) { if(extension.equals("java")) { icon = javaIcon; } if(extension.equals("html")) { icon = htmlIcon; } } 10 Ingeniería en Computación , Universidad de La Serena Prof. Dr. Eric Jeltsch F. Programación en Java2 Tema: MasMenu return icon; } // Si la direccion es traversable. public Boolean isTraversable(File f) { return null; // L&F FileView encontrara esta salida } } // Recupera la extension de un archivo. private String getExtension(File f) { String fileNombre = f.getName(); int periodIndex = fileNombre.lastIndexOf('.'); String extension = null; if(periodIndex > 0 && periodIndex < fileNombre.length() - 1) { extension = fileNombre.substring(periodIndex+1).toLowerCase(); } return extension; } 11 Ingeniería en Computación , Universidad de La Serena Prof. Dr. Eric Jeltsch F. Programación en Java2 Tema: MasMenu CutAction y PasteAction import import import import javax.swing.*; javax.swing.event.*; java.awt.*; java.awt.event.*; // La clase frame Swing public class TAction extends JFrame { // Declara los datos miembros CutAction miCutAction = null; PasteAction miPasteAction = null; Container miContainer = null; JPopupMenu miPopupMenu = null; JTextArea miTextArea = null; // Iconos para ser usados sobre la barra de botones e items de menus Icon miCutIcon = new ImageIcon("cut.gif"); Icon miPasteIcon = new ImageIcon("paste.gif"); public TAction() { // 1. Llamada a super con el titulo previsto. super("Cut y Paste es Frame TAction"); // 2. Extraer el tratamiento sobre el frame en content pane. miContainer = this.getContentPane(); // 3. Crea un panel y lo agrega al tope del frame. JPanel miPanel = new JPanel(false); miContainer.add(miPanel, BorderLayout.NORTH); miPanel.setLayout(new GridLayout(2,1)); // 4. Crea una barra de menu y lo attach al panel. JMenuBar miMenuBar = new JMenuBar(); miPanel.add(miMenuBar); // 5. Crea el archivo (File) y Edit en el menu. 12 Ingeniería en Computación , Universidad de La Serena Prof. Dr. Eric Jeltsch F. Programación en Java2 Tema: MasMenu JMenu miFileMenu = new JMenu("File"); JMenu miEditMenu = new JMenu("Edit"); // 6. Agrega el menu al menu de la barra. miMenuBar.add(miFileMenu); miMenuBar.add(miEditMenu); // 7. Crea un toolbar y lo attach al panel. JToolBar miToolBar = new JToolBar(); miPanel.add(miToolBar); // 8. Crea los objetos Accion para las operaciones cut y paste. miCutAction = new CutAction("Cut", miCutIcon); miPasteAction = new PasteAction("Paste", miPasteIcon); // 9. Agrega los fuentes de acciones comunes a sus pares. JMenuItem miActionCutItem = miEditMenu.add(miCutAction); JMenuItem miActionPasteItem = miEditMenu.add(miPasteAction); JButton miCutButton = miToolBar.add(miCutAction); JButton miPasteButton = miToolBar.add(miPasteAction); miCutButton.setText("");// botones no necesitan tener los labels miPasteButton.setText(""); // 10. Crea y agrega el texto de area al content pane. miTextArea = new JTextArea("Testeando las interfaces en la Accion " +"\noperando las herramientas de la barra de botones, " +"\nmenu items en el menu edit, y " +"\nmenu items en el menu pop-up."); miTextArea.setFont(new Font("Monospaced", Font.PLAIN, 14)); miContainer.add(miTextArea); // 11. Crea un menu pop-up y lo agrega al area de texto. miPopupMenu = new JPopupMenu("Demo Menu Pop-up"); JMenuItem miCutPopupMenuItem = miPopupMenu.add(miCutAction); JMenuItem miPastePopupMenuItem = miPopupMenu.add(miPasteAction); // 12. Crea un menu pop-up listener y lo registra con text area. PopupMenuListener pml = new PopupMenuListener(); miTextArea.addMouseListener(pml); // 13. Cerrar el frame. addWindowListener(new WindowEventTrato()); setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); } // 14. Setea el tamaño del frame y lo despliega. setSize(350, 200); show(); // 15. La clase Accion Cut que extiende AbstractAction. class CutAction extends AbstractAction { public CutAction(String miLabel, Icon miIcon) { super(miLabel, miIcon); } } public void actionPerformed(ActionEvent ae) { miTextArea.cut(); } 13 Ingeniería en Computación , Universidad de La Serena Prof. Dr. Eric Jeltsch F. Programación en Java2 Tema: MasMenu // 16. La clase Action Paste que extiende AbstractAction. class PasteAction extends AbstractAction { public PasteAction(String miLabel, Icon miIcon) { super(miLabel, miIcon); } } public void actionPerformed(ActionEvent ae) { miTextArea.paste(); } // 17. El menu pop-up listener. class PopupMenuListener extends MouseAdapter { public void mousePressed(MouseEvent me) { showPopup(me); } public void mouseReleased(MouseEvent me) { showPopup(me); } private void showPopup(MouseEvent me) { if (me.isPopupTrigger()) { miPopupMenu.show(me.getComponent(), me.getX(), me.getY()); } } } } // 18. La clase Listener para cerrar el frame. class WindowEventTrato extends WindowAdapter { public void windowClosing(WindowEvent evt) { System.exit(0); } } // 19. El metodo main. public static void main(String[] args) { TAction miAccionFrame = new TAction(); } 14 Ingeniería en Computación , Universidad de La Serena Prof. Dr. Eric Jeltsch F. Programación en Java2 Tema: MasMenu Actividad (Editor de Texto) Escriba un editor de texto sencillo, en la cual el programa principal deberá tener un objeto del tipo Texteditor, que es en el sector donde podrá trabajar su texto. Considere dentro de su programa un menu, con las opciones de "Nuevo Archivo", "Abrir Archivo", "Guardar Archivo como" y "Cerrar Archivo". La interface de usuario debe verse más o menos así: 15 Ingeniería en Computación , Universidad de La Serena Prof. Dr. Eric Jeltsch F. Programación en Java2 Tema: MasMenu Alguna información sobre los archivos si desea incorporar alguna de estas informaciones en su archivo ya sea para informar al usuario o para su propia información. /* TestFile.java */ import java.io.*; import java.util.*; public class TestFile { public static void main(String[] args) { File fil = new File("TestFile.java"); TestFile.printFileInfo(fil); fil = new File(".."); TestFile.printFileInfo(fil); } static void printFileInfo(File fil) { System.out.println("Name= "+fil.getName()); System.out.println("Path= "+fil.getPath()); System.out.println("AbsolutePath= "+fil.getAbsolutePath()); System.out.println("Parent= "+fil.getParent()); System.out.println("exists= "+fil.exists()); System.out.println("canWrite= "+fil.canWrite()); System.out.println("canRead= "+fil.canRead()); 16 Ingeniería en Computación , Universidad de La Serena Prof. Dr. Eric Jeltsch F. } } Programación en Java2 Tema: MasMenu System.out.println("isFile= "+fil.isFile()); System.out.println("isDirectory= "+fil.isDirectory()); if (fil.isDirectory()) { String[] fils = fil.list(); for (int i=0; i<fils.length; ++i) { System.out.println(" "+fils[i]); } } System.out.println("isAbsolute= "+fil.isAbsolute()); System.out.println( "lastModified= "+(new Date(fil.lastModified())) ); System.out.println("length= "+fil.length()); System.out.println(""); 17 Ingeniería en Computación , Universidad de La Serena