Sei sulla pagina 1di 13

Swing, la solucin actual de Java para crear GUIs

Marcela Caldern Emilio Davis

Introduccin:
El paquete Swing es parte de la JFC (Java Foundation Classes) en la plataforma Java. La JFC provee facilidades para ayudar a la gente a construir GUIs. Swing abarca componentes como botones, tablas, marcos, etc... Las componentes Swing se identifican porque pertenecen al paquete javax.swing. Swing existe desde la JDK 1.1 (como un agregado). Antes de la existencia de Swing, las interfaces grficas con el usuario se realizaban a travs de AWT (Abstract Window Toolkit), de quien Swing hereda todo el manejo de eventos. Usualmente, para toda componente AWT existe una componente Swing que la reemplaza, por ejemplo, la clase Button de AWT es reemplazada por la clase JButton de Swing (el nombre de todas las componentes Swing comienza con "J"). Las componentes de Swing utilizan la infraestructura de AWT, incluyendo el modelo de eventos AWT, el cual rige cmo una componente reacciona a eventos tales como, eventos de teclado, mouse, etc... Es por esto, que la mayora de los programas Swing necesitan importar dos paquetes AWT: java.awt.* y java.awt.event.*. Ojo: Como regla, los programas no deben usar componenetes pesados de AWT junto a componentes Swing, ya que los componentes de AWT son siempre pintados sobre los de Swing. (Por componentes pesadas de AWT se entiende Menu, ScrollPane y todas las componentes que heredan de las clases Canvas y Panel de AWT). Compilacin: Estndar.

Estructura bsica de una aplicacin Swing.

Una aplicacin Swing se construye mezclando componentes con las siguientes reglas.

Debe existir, al menos, un contenedor de alto nivel (Top-Level Container), que provee el soporte que las componentes Swing necesitan para el pintado y el manejo de eventos. Otras componentes colgando del contenedor de alto nivel (stas pueden ser contenedores o componentes simples).

Ejemplo 1:
import javax.swing.*; import java.awt.*; import java.awt.event.*; public class HolaMundoSwing { public static void main(String[] args) { JFrame frame = new JFrame("HolaMundoSwing"); final JLabel label = new JLabel("Hola Mundo"); frame.getContentPane().add(label); //frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.addWindowListener(new java.awt.event.WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0); } } ); frame.pack(); frame.setVisible(true); } }

En las primeras lneas se importan los paquetes necesarios.


import javax.swing.*; import java.awt.*; import java.awt.event.*;

Luego se declara la clase HolaMundoSwing y en el mtodo main se setea el top level container:
public class HolaMundoSwing { public static void main(String[] args) { JFrame frame = new JFrame("HolaMundoSwing"); ... frame.pack(); frame.setVisible(true); } }

En el ejemplo, slo hay un contenedor de alto nivel, un JFrame. Un frame implementado como una instancia de la clase JFrame es una ventana con decoraciones, tales como, borde, ttulo y botones como conos y para cerrar la ventana. Aplicaciones con un GUI tpicamente usan, al menos, un frame. Adems, el ejemplo tiene un componente, una etiqueta que dice "Hola Mundo".

final JLabel label = new JLabel("Hola Mundo"); //construye el JLabel. frame.getContentPane().add(label); label al frame. //agrega el

Para que el botn de cerrar cierre la ventana, hay dos opciones:


frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //JDK 1.3+ frame.addWindowListener(new java.awt.event.WindowAdapter(){ //versiones anteriores public void windowClosing(WindowEvent e){ System.exit(0); } } );

Principales aspectos de una aplicacin Swing


Como ya se dijo antes, cada aplicacin Swing debe tener al menos un top-level container que contendr toda la aplicacin, estos pueden ser

javax.swing.JFrame: Una ventana independiente. javax.swing.JApplet: Un applet. Dilogos: ventanas de interaccin sencilla con el usuario como por ejemplo: o java.swing.JOptionPane: Ventana de dilogo tipo SI_NO, SI_NO_CANCELAR, ACEPTAR, etc... o java.swing.JFileChooser: Ventana para elejir un archivo. o java.swing.JColorChooser o etc.

A un contenedor se le pueden agregar otros contenedores o componentes simples, para ver una muestra visual de cada componente y sus respectivas descripciones presione aqu Configurando el "Look & Feel" de una aplicacin Swing permite setear dinmicamente el aspecto y la forma de interaccin de una aplicacin, por ejemplo el siguiente cdigo setea el L&F al estilo Java
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassNam e())

Existen los siguientes L&F:


Java look & feel CDE/Motif look & feel Windows look & feel

Configurando el "Layout" de un contenedor Varias componentes pueden contener otras componentes dentro, para determinar de qu modo esas componentes se organizarn visualmente se utiliza el concepto de Layout. Por ejemplo, el siguiente cdigo crea un frame y setea el layout del pao de contenidos (porcin central de la ventana) con BorderLayout y finalmente agrega una etiqueta al sur de la ventana.
JFrame frame= new Jframe(); frame.getContentPane().setLayout(new BorderLayout()); JLabel label=new JLabel("yo voy abajo"); frame.add(label, BorderLayout.SOUTH);

A continuacin se muestran los diferentes layout estndares de swing.

Manejando eventos Cada vez que el usuario interacta con la aplicacin se gatilla un evento, para que una componente determinada reaccione frente a un evento, debe poseer un "escuchador" con, al menos, un mtodo determinado que se ejecutar al escuchar un evento en particular, por ejemplo, en el siguiente cdigo se crea un botn que al ser presionado imprime en la salida estndar un mensaje.
JButton boton=new JButton("Un botn"); boton.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ System.out.println("Me apretaron"); } });

Swing puede generar un variado set de eventos, en la siguiente tabla se resumen los ms comunes con sus respectivos "escuchadores".

Ejemplos de eventos y sus escuchadores Accin que gatilla un evento El usario hace un click, presiona Return en un rea de texto o selecciona un men El usuario escoje un frame (ventana principal) Tipo de escuchador
ActionListener WindowListener

El usuario hace un click sobre una componente MouseListener El usuario pasa el mouse sobre una componente MouseMotionListener Una componente se hace visible Una componente adquiere el foco del teclado Cambia la seleccin en una lista o tabla
ComponentListener FocusListener ListSelectionListener

Threads y Swing
Como regla general slo un thread debe accesar una componente Swing, para lograr esto, la receta es que slo el thread que atiende los eventos invoque los mtodos de las componentes. El siguiente cdigo sigue el patrn "The Single-Thread Rule".
//Ejemplo Thread-safe public class MyApplication { public static void main(String[] args) { JFrame f = new JFrame(...); ...//agregar componentes al frame f.pack(); f.setVisible(true); //No hacer mas GUI } ... //Toda la manipulacin de la GUI -- setText, getText, etc. //es efectuada por manejadores de eventos como actionPerformed(). ... }

Nota: algunos mtodos dentro de la API de Swing estn marcados como "thread safe", stos pueden ser invocados concurrentemente por cualquier thread, el texto que indica esto es: "This method is thread safe, although most Swing methods are not."

Ejemplo2: Editor de texto simple

El cdigo fuente est adjunto edit

El siguiente diagrama sirve para comprender mejor el ejemplo

Explicacin paso a paso:

El main de la aplicacin sigue el patrn que utiliza la herramienta IBM Visual Age for Java 3.5:
public static void main(java.lang.String[] args) { Edit aplication = new Edit("Editor simple"); aplication.initialize(); aplication.initConnections(); aplication.pack(); aplication.setSize(500, 400); aplication.setLocation(100, 100); aplication.setVisible(true); }

Edit es una clase que extiende de javax.swing.JFrame que corresponde a un toplevel container, aplication es una instancia de esa clase y al constructor se le entrega como parmetro el ttulo de la ventana. A continuacin se invoca el mtodo initialize() donde se construirn todos las componentes de la aplicacin. Luego se invoca initConnections() donde las componentes que requieren atencin de eventos se suscriben a stos. Finalmente se empaqueta la ventana, se define el tamao y posicin inicial y se deja visible al usuario.

Inicializacin de la aplicacin
public void initialize() { //Define que el Layout del contenedor sea de tipo BorderLayout this.getContentPane().setLayout(new BorderLayout()); // Clase anonima para que la aplicacion se cierre al apretar la X (boton esquina superior derecha) this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { if (!isSaved && !editPane.getText().equals("")) askSave(); System.exit(0); } }); /*****JMenuBar*****/ menuBar = new JMenuBar(); fileMenu = new JMenu("Archivo"); newMenu = new JMenuItem("Nuevo"); openMenu = new JMenuItem("Abrir"); saveMenu = new JMenuItem("Guardar"); exitMenu = new JMenuItem("Salir"); //Agrega los items al menu

fileMenu.add(newMenu); fileMenu.add(openMenu); fileMenu.add(saveMenu); fileMenu.addSeparator(); fileMenu.add(exitMenu); //Agrega el menu a la barra de menu menuBar.add(fileMenu); //Setea esa bara de menu para el frame this.setJMenuBar(menuBar); /*****JToolBar*****/ toolBar = new JToolBar(); //Crea los botones asignando sendas imgenes y los agrega al toolbar openButton = new JButton(); openButton.setIcon(new ImageIcon(getClass().getResource("/open.gif"))); openButton.setMargin(new Insets(0, 0, 0, 0)); toolBar.add(openButton); saveButton = new JButton(); saveButton.setIcon(new ImageIcon(getClass().getResource("/save.gif"))); saveButton.setMargin(new Insets(0, 0, 0, 0)); toolBar.add(saveButton); //agrega un separador en la toolbar toolBar.addSeparator(); copyButton = new JButton(); copyButton.setIcon(new ImageIcon(getClass().getResource("/copy.gif"))); copyButton.setMargin(new Insets(0, 0, 0, 0)); toolBar.add(copyButton); cutButton = new javax.swing.JButton(); cutButton.setIcon(new ImageIcon(getClass().getResource("/cut.gif"))); cutButton.setMargin(new Insets(0, 0, 0, 0)); toolBar.add(cutButton); pasteButton = new javax.swing.JButton(); pasteButton.setIcon(new ImageIcon(getClass().getResource("/paste.gif"))); pasteButton.setMargin(new Insets(0, 0, 0, 0)); toolBar.add(pasteButton); //Agrega el toolbar en el norte del contenedor this.getContentPane().add(toolBar, BorderLayout.NORTH); /*****Status bar*****/ statusPanel = new JPanel(); statusPanel.setLayout(new BorderLayout()); //crea las etiquetas para la barra de estado statusMsg1 = new JLabel("Estado: "); statusMsg2 = new JLabel(); statusPanel.add(statusMsg1, BorderLayout.WEST); statusPanel.add(statusMsg2, BorderLayout.CENTER); //Agrega el panel de satus al sur del contenedor this.getContentPane().add(statusPanel, BorderLayout.SOUTH);

/*****Text Editor*****/ editPane = new JEditorPane(); editPane.setText(""); scrollPaneRight = new JScrollPane(editPane); /*****List*****/ list=new JList(); scrollPaneLeft=new JScrollPane(list); openSelectedButton=new JButton("Abrir"); /*****leftPanel*****/ leftPanel=new JPanel(new BorderLayout()); leftPanel.add(scrollPaneLeft,BorderLayout.CENTER); leftPanel.add(openSelectedButton,BorderLayout.SOUTH); /*****Split Panel*****/ //Define un contenedor con division izq-der splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); splitPane.setRightComponent(scrollPaneRight); splitPane.setLeftComponent(leftPanel); this.getContentPane().add(splitPane, BorderLayout.CENTER); }

Suscripcin a eventos
public void initConnections() { //se suscriben todas las componentes que quieren escuchar los eventos newMenu.addActionListener(eventHandler); openMenu.addActionListener(eventHandler); saveMenu.addActionListener(eventHandler); exitMenu.addActionListener(eventHandler); openButton.addActionListener(eventHandler); saveButton.addActionListener(eventHandler); copyButton.addActionListener(eventHandler); cutButton.addActionListener(eventHandler); pasteButton.addActionListener(eventHandler); openSelectedButton.addActionListener(eventHandler); }

En la clase Edit se define la clase interna EventHandler que implementa java.awt.event.ActionListener Cuando se gatilla un evento, se le pregunta el source, es decir, en qu componente se gener, y dependiendo de la respuesta se ejecuta la accin correspondiente.
... class EventHandler implements ActionListener { public void actionPerformed(ActionEvent e) { //Si se elige salir en el menu

if (e.getSource() == exitMenu) { //Si el archivo abierto no esta en blanco y no esta guardado if (!isSaved && !editPane.getText().equals("")) askSave(); System.exit(0); } //Si se elige abrir un archivo en el menu o con el boton de abrir en el toolbar if (e.getSource() == openMenu || e.getSource() == openButton) { if (!isSaved && !editPane.getText().equals("")) askSave(); openFile(); } //Si se elige en el menu editar un archivo en blanco if (e.getSource() == newMenu) { if (!isSaved && !editPane.getText().equals("")) askSave(); newFile(); } //Si se elige guardar en el menu o en el toolbar if (e.getSource() == saveMenu || e.getSource() == saveButton) saveFile(); //copy if (e.getSource() == copyButton) editPane.copy(); //cut if (e.getSource() == cutButton) editPane.cut(); //paste if (e.getSource() == pasteButton) editPane.paste(); //Si se elige el boton abrir la lista del lado izquierdo if (e.getSource() == openSelectedButton) openSelectedFile(); }; }; //se crea un objeto ActionListener que capturar todos los eventos de tipo accin ActionListener eventHandler = new EventHandler(); ...

Descripcin de algunas funcionalidades de la aplicacin


Al invocar el mtodo openFile() se ejecuta el siguiente cdigo:

public void openFile() { //Si no existe el file chooser, crea uno if (fileChooser == null) { fileChooser = new JFileChooser(); } //Valor que retorna al elegir una opcion en el file chooser int retVal = fileChooser.showOpenDialog(this); //Si se escogio Ok, (o abrir) if (retVal == fileChooser.APPROVE_OPTION) { //El path absoluto del archivo elegido fileName = fileChooser.getSelectedFile().getAbsolutePath(); try { //Pasa el nombre del archivo a URL java.net.URL url = fileChooser.getSelectedFile().toURL(); statusMsg2.setText("abriendo " + fileName); //Abre el archivo elegido en el panel de texto editPane.setPage(url); isSaved = false; //Se agrega el archivo abierto a la lista de la izquierda agregaLista("" + fileName); } catch (Exception ioe) { statusMsg2.setText(ioe.getMessage()); } } }

El mtodo saveFile() es similar, abriendo, en vez de un dilogo de apertura de archivos uno de guardado
public void saveFile() { //Si no existe, crea uno if (fileChooser == null) { fileChooser = new JFileChooser(); } //Abre un dilogo de guardado de archivos int retVal = fileChooser.showSaveDialog(this); if (retVal == fileChooser.APPROVE_OPTION) { fileName = fileChooser.getSelectedFile().getAbsolutePath(); try { statusMsg2.setText("Guardando "+fileName); //Toma el texto que hay en el panel de texto String text=editPane.getText(); java.io.FileWriter fileWriter=new java.io.FileWriter(fileName); java.io.BufferedWriter br = new java.io.BufferedWriter(fileWriter);

br.write(text); br.close(); isSaved=true; //Agrega el archivo a la lista de la izquierda agregaLista(""+fileName); } catch (Exception ioe) { statusMsg2.setText(ioe.getMessage()); } } }

El mtodo agregaLista(String fileName) agrega una archivo a la lista de archivos abiertos


public void agregaLista(String file) { if (fileVector.contains(file)) return; fileVector.add(file); Collections.sort(fileVector); list.setListData(fileVector); }

Y el mtodo askSave() abre una ventana modal que le pregunta al usuario si quiere guardar el archivo abierto (se llama cuando el usuario no ha grabado el archivo y quiere abrir otro, cerrar la aplicacin o escribir uno nuevo.
public void askSave() { //Componente que muestra ventanas de opciones JOptionPane optionPane=new JOptionPane(); Object[] opciones={"S","No"}; //Dialogo modal SI_NO int ret=optionPane.showOptionDialog(this,"Desea guardar? ","Pregunta",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE,nu ll,opciones,opciones[0]); //Si la opcion escogida es Si if(ret==JOptionPane.YES_OPTION) saveFile(); }

Compilar y probar el ejemplo


Para compilar y probar el ejemplo se debe tener la JDK1.2+ y seguir los siguientes pasos

[prompt:] javac Edit.java [prompt:] java Edit

Ejemplo 3: Editor de texto + navegador

El cdigo fuente est adjunto edit2

Potrebbero piacerti anche