martes

JPANEL:El siguiente ejemplo java1418.java, se aprovecha de algunos de los ejemplos anteriores para poder implementar los diferentes paneles. Todos se construyen como descendientes de JPanel, así que en el programa se colocará cada uno de los ejemplos anteriores en su propio panel dentro del JTabbedPane.

import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;
import com.sun.java.swing.border.*;

public class java1418 extends JPanel {
static Object objetos[][] = {
{ "AWT-Clon",java1401.class },
{ "Bordes",java1402.class },
{ "Botones",java1404.class },
{ "Grupo de Botones",java1406.class },
{ "Listas y Combo",java1407.class },
{ "Barras",java1413.class },
{ "Arbol",java1414.class },
{ "Tabla",java1416.class },
};

static JPanel creaPanel( Class clase ) {
String titulo = clase.getName();
titulo = titulo.substring( titulo.lastIndexOf('.') + 1 );
JPanel panel = null;
try {
panel = (JPanel)clase.newInstance();
} catch( Exception e ) {
System.out.println( e );
}
panel.setBorder( new TitledBorder( titulo ) );
return( panel );
}

public java1418() {
setLayout( new BorderLayout() );
JTabbedPane pestana = new JTabbedPane();
for( int i=0; i < objetos.length; i++ ) {
pestana.addTab( (String)objetos[i][0],
creaPanel( (Class)objetos[i][1] ) );
}
add( pestana,BorderLayout.CENTER );
pestana.setSelectedIndex( objetos.length/2 );
}

public static void main( String args[] ) {
JFrame frame = new JFrame( "Tutorial de Java, Swing" );
frame.addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent evt ) {
System.exit( 0 );
}
} );
frame.getContentPane().add( new java1418(),BorderLayout.CENTER );
frame.setSize( 460,350 );
frame.setVisible( true );
}
}

Se ha utilizado un array para la configuración: el primer elemento es el objeto String que será colocado en la pestaña y el segundo corresponde al objeto de la clase JPanel que será presentado dentro del correspondiente Panel. En el constructor del ejemplo se puede observar que se utilizan los dos métodos importantes del JTabbedPane: addTab() que crea una nueva pestaña y setSelectedIndex() que indica el panel que se va a presentar en primer lugar al arrancar el programa; en este caso se selecciona uno de en medio para mostrar que no es necesario comenzar siempre por el primero. La figura siguiente reproduce esta ventana inicial, en la que aparecen las barras de desplazamiento al igual que se ilustraba uno de los ejemplos anteriores de este capítulo.

En la llamada al método addTab() se le proporciona la cadena que debe colocar en la pestaña y cualquier Componente del AWT. No es necesario que sea un JCompomponent, sino cualquier Componente del AWT, entre los cuales se encuentra, evidentemente, el JComponent, que deriva del Component del AWT. El Componente se presentará sobre el panel y ya no será necesario ningún control posterior, el JTabbedPane se encarga de todo.

El trozo más interesante del código del ejemplo es el correspondiente al método creaPanel() que coge el objeto Class de la clase que se quiere crear y utiliza el método newInstance() para crear uno, moldeándolo a JPanel; desde luego, esto asume que la clase que se quiere añadir debe heredar de JPanel, sino no serviría de nada. Añade un TitledBorder que contiene el nombre de la clase y devuelve el resultado como un JPanel para que sea utilizado en addTab().

  static JPanel creaPanel( Class clase ) {
String titulo = clase.getName();
titulo = titulo.substring( titulo.lastIndexOf('.') + 1 );
JPanel panel = null;
try {
panel = (JPanel)clase.newInstance();
} catch( Exception e ) {
System.out.println( e );
}
panel.setBorder( new TitledBorder( titulo ) );
return( panel );
}
JMENUBAR:
  • JMenuBar. Es la barra de menú principal. Una barra horizontal alargada en la que se colocarán las distintas opciones. Si miras en tu navegador, arriba, verás una barra de estas con opciones como "Archivo", "Editar", etc.

  • JMenu. Es una de las cosas que se pueden añadir a un JMenuBar o a otro JMenu. Cuando añadimos uno de estos, tendremos un algo que al pinchar despliega un nuevo menú. Si en tu navegador, arriba donde pone "Archivo" pinchas con el ratón, verás que se despliega un menú con más opciones como "Abrir", "Guardar como", etc. Este "Archivo" si estuviera hecho en java sería un JMenu, ya que al pincharlo no hace nada, sólo despliega otro menú. Si añades un JMenu dentro de otro, tendrás un nuevo submenú que se despliega. Por ejemplo, si miras abajo en tu windows, en el botón de "Inicio" de abajo a la izquierda, lo pinchas y sale un menú. Ese "Inicio" sería un JMenu si estuviese hecho en java. En las opciones que despliega, ves que "Programas" tiene una flechita a la deracha. Poniendo ahí el ratón sale otro nuevo menú. Eso quiere decir que "Programas" también sería un JMenu que está dentro de JMenu "Inicio".

  • JMenuItem. Por fin, este es el currito. Es el que cuando lo pinchas hace algo útil, como "guardar como", "abrir", etc.

  • JSeparator. Este sólo sirve para poner una rayita y separar varios JMenuItem. Por ejemplo, dentro de "Editar", las opciones "Copiar", "Cortar" y "Pegar" suelen estar separadas con rayitas de otras opciones en el mismo menú. Estos son los JSeparator.
JLIST: JList tiene un constructor al que se puede pasar un array de objetos String para que los presente. El ejemplo java1407.java, muestra el uso básico de estos dos componentes.
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;

public class java1407 extends JPanel {

public java1407() {
setLayout( new GridLayout( 2,1 ) );

JList lista = new JList( java1406.ids );
add( new JScrollPane( lista ) );

JComboBox combo = new JComboBox();
for( int i=0; i < 100; i++ )
combo.addItem( Integer.toString( i ) );
add( combo );
}

public static void main( String args[] ) {
java1407 lista = new java1407();
JFrame ventana = new JFrame();

ventana.getContentPane().add( lista,BorderLayout.CENTER );

ventana.addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent evt ) {
System.exit( 0 );
}
} );

ventana.setSize( 200,200 );
ventana.setTitle( "Tutorial de Java, Swing" );
ventana.setVisible( true );
}
}

La imagen siguiente es el resultado que se obtiene en pantalla tras la ejecución del ejemplo, y después de haber seleccionado uno de los elementos en la caja combo y abrirla para proseguir la selección de otra de las opciones o elementos que se permite elegir.

Una cosa que se ha mantenido con respecto a las listas de antes es que los objetos JList no proporcionan automáticamente la posibilidad de scroll o desplazamiento del contenido, que es una cosa que se espera que haga automáticamente, y resulta un poco chocante. No obstante, el añadir scroll a listas es sumamente sencillo, ya que es suficiente con incluir la JList en un JScrollPane, y todos los detalles del desplazamiento del contenido serán ya manejados bajo la responsabilidad del sistema.

Aunque lo más frecuente es que cada elemento seleccionable de una lista sea una etiqueta, Swing proporciona al componente JList también la posibilidad de presentar gráficos, con o sin texto asociado, y también proporciona un control adicional de eventos para adecuarse a los que se producen en la manipulación de este tipo de Componentes. Es decir, que en una lista también se pueden incluir instancias de clases como JButton, JTextField, JCheckBox, e incluso JTextArea, que es un componente multilínea.

En el ejemplo java1408.java se muestra precisamente una lista en la que se utilizan instancias de la clase JTextArea, para mostrar los valores que se cargan en la lista, que corresponden a un extracto del índice del Tutorial:

    "Capitulo 4\nIntroduccion al Lenguaje Java",
"Capitulo 5\nConceptos Basicos de Java",
"Capitulo 6\nProgramas Basicos en Java",
"Capitulo 7\nEl Depurador de Java",
"Capitulo 8\nClases Java",
"Capitulo 9\nExcepciones en Java"

Cada valor incluye el carácter de nueva línea, \n, para forzar el salto de línea en medio del texto.

class MiRendererDeLista extends JTextArea implements ListCellRenderer {

public Component getListCellRendererComponent(
JList lista,Object valor,int indice,
boolean seleccionado, boolean conFoco ) {

setBorder( new BevelBorder( BevelBorder.RAISED ) );
// Presenta el text correspondiente al item
setText( valor.toString() );
// Pinta en los colores indicados y con la fuente seleccionada...
if( seleccionado ) {
// .. en el caso de un item marcado (rojo/blanco)
setBackground( Color.red );
setForeground( Color.white );
}
else {
// .. en el caso de un item no marcado (gris/negro)
setBackground( Color.lightGray );
setForeground( Color.black );
}
return( this );
}
}

El código es bastante simple, y la parte más interesante es la correspondiente a la clase anidada MiRendererDeLista, reproducido antes, que implementa un controlador diferente para cada celda de la lista, extendiendo en este caso a JTextArea en lugar de JLabel, como suele ser habitual. El resultado de la ejecución del ejemplo es el que muestra la figura.

Aunque el componente JTextArea también tiene sus limitaciones, como son el no permitir el uso de gráficos, se puede observar que las posibilidades que se presentan al programador se han visto tremendamente incrementadas con la inclusión de este tipo de Componente y con las nuevas características que proporciona Swing. En este caso, incluso es posible hacer que la altura de la celda esté recortada, en el caso de utilizar fuentes de caracteres muy grandes, debido a que la altura de cada uno de los elementos seleccionables de la lista se determina en el momento en que son construidos.

JLABEL:

Si se echa un vistazo a los constructores de la clase JLabel, se puede observar claramente que Swing ofrece un API mucho más rico, presentando constructores con habilidades no disponibles en el AWT. El ejemplo java1403.java, crea varias instancias de la clase JLabel utilizando algunas de las características que permite Swing, como por ejemplo la utilización de gráficos, que resulta extremadamente simple.

import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;

class java1403 extends JPanel {

public java1403() {
setLayout( new GridLayout( 2,2 ) );

JLabel etiq1 = new JLabel();
etiq1.setText( "Etiqueta1" );
add( etiq1 );

JLabel etiq2 = new JLabel( "Etiqueta2" );
etiq2.setFont( new Font( "Helvetica", Font.BOLD, 18 ) );
add( etiq2 );

Icon imagen = new ImageIcon( "star0.gif" );
JLabel etiq3 = new JLabel( "Etiqueta3", imagen,SwingConstants.CENTER );
etiq3.setVerticalTextPosition( SwingConstants.TOP );
add( etiq3 );

JLabel etiq4 = new JLabel( "Etiqueta4",SwingConstants.RIGHT );
add( etiq4 );
}

public static void main( String args[] ) {
JFrame ventana = new JFrame( "Tutorial de Java, Swing" );

ventana.addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent evt ){
System.exit( 0 );
}
} );
ventana.getContentPane().add( new java1403(),BorderLayout.CENTER );
ventana.setSize( 300,150 );

ventana.setVisible( true );
}
}

La figura siguiente es el resultado de la ejecución del programa anterior, donde se puede observar que en la Etiqueta2 se muestra el cambio de fuente de caracteres y en la Etiqueta3 se incluye una imagen. En este último caso, el tamaño de la imagen es el que determina el tamaño mínimo de la etiqueta.

El tipo de letra con que se presenta el texto de la etiqueta se puede cambiar fácilmente, basta con crear una nueva fuente de caracteres e invocar al método setFont() de la clase JLabel para que el cambio surta efecto. La fuente de caracteres puede ser cualquiera de las estándar, dentro de los tamaños soportados por la máquina virtual Java de la plataforma. El control de la fuente de caracteres utilizada para la etiqueta se puede realizar con una línea de código semejante a la siguiente:

label.setFont( new Font( "Dialog",Font.PLAIN,12 ) );

Los colores del texto y del fondo de la etiqueta también se pueden cambiar de forma muy sencilla, mediante la invocación de los métodos setForeground() y setBackground().

Navegador

J COMBOBOX:

JComboBox, es un componente swing, y como tal, podemos crear nuestro propio modelo de datos al momento de crear y manipular a este componente(en este caso: jComboBox).

En este caso, el ejercicio intenta mostrar la forma sencilla al momento de implementar nuestro propio Modelo de datos para un componente JComboBox.

El ejercicio consiste, en una tipica “barra de direcciones de un navegador”, ingresas la direccion, entras a la pagina, luego el navegador comprueba si existe la direccion,en el caso de no existir, agrega la direccion de la pagina a la barra de direcciones, para un posterior facil acceso.

Bien, para este ejercicio implementaremos 3 clase. la vista(WindowDemoEditaCombo), el control(ControlDemoEditaCombo), y el Modelo del JComboBox (ModeloCombo).

WindowDemoEditaCombo, esta es la clase, que dibuja los componentes swing; En este caso para crear un JComboBox, necesario primero crear nuestro modelo, el cual recibe una cadena de caracteres, los mismos que seran mostrados como items en el combo.

J FRAME:Para iniciar maximizado un JFrame lo que realizamos es setearle mediante setExtendedState() el estado en que queremos que aparezca al realizarle un setVisible(true).

Para ello utilizamos la constante JFrame.MAXIMIZED_BOTH de la siguiente forma:

  1. import javax.swing.JFrame;
  2. public class MaximizarJFrame{
  3. public static void main(String[] args) {
  4. final JFrame frame = new JFrame("Prueba JFrame");
  5. frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
  6. frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
  7. frame.setVisible(true);
  8. }
  9. }

además podemos indicarle otras opciones:

  • JFrame.NORMAL: Inicializa el JFrame en estado Normal
  • JFrame.ICONIFIED: Inicializa el JFrame en estado Minimizado.
  • JFrame.MAXIMIZED_HORIZ: Inicializa el JFrame en estado Maximizado Horizontalmente
  • JFrame.MAXIMIZED_VERT: Inicializa el JFrame en estado Maximizado Verticalmente
  • JFrame.MAXIMIZED_BOTH: Inicializa el JFrame en estado Maximizado en ambos sentidos

jueves

SWING

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 gráficas con el usuario se realizaban a través 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 cómo una componente reacciona a eventos tales como, eventos de teclado, mouse, etc... Es por esto, que la mayoría 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).

Compilación: Estándar.



Estructura básica de una aplicación Swing.


Una aplicación 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 líneas se importan los paquetes necesarios.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
Luego se declara la clase HolaMundoSwing y en el método 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, sólo 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, título y botones como íconos y para cerrar la ventana. Aplicaciones con un GUI típicamente usan, al menos, un frame.

Además, 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); //agrega el label al frame.

Para que el botón 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 aplicación Swing

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

  • javax.swing.JFrame: Una ventana independiente.
  • javax.swing.JApplet: Un applet.
  • Diálogos: ventanas de interacción sencilla con el usuario como por ejemplo:
    • java.swing.JOptionPane: Ventana de diálogo tipo SI_NO, SI_NO_CANCELAR, ACEPTAR, etc...
    • java.swing.JFileChooser: Ventana para elejir un archivo.
    • java.swing.JColorChooser
    • 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 aplicación

Swing permite setear dinámicamente el aspecto y la forma de interacción de una aplicación, por ejemplo el siguiente código setea el L&F al estilo Java

UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName())

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 organizarán visualmente se utiliza el concepto de Layout. Por ejemplo, el siguiente código crea un frame y setea el layout del paño de contenidos (porción 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 continuación se muestran los diferentes layout estándares de swing.

Manejando eventos

Cada vez que el usuario interactúa con la aplicación se gatilla un evento, para que una componente determinada reaccione frente a un evento, debe poseer un "escuchador" con, al menos, un método determinado que se ejecutará al escuchar un evento en particular, por ejemplo, en el siguiente código se crea un botón que al ser presionado imprime en la salida estándar un mensaje.

 JButton boton=new JButton("Un botón");
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 más comunes con sus respectivos "escuchadores".

Ejemplos de eventos y sus escuchadores
Acción que gatilla un evento Tipo de escuchador
El usario hace un click, presiona Return
en un área de texto o selecciona un menú
ActionListener
El usuario escoje un frame (ventana principal) WindowListener
El usuario hace un click sobre una componente MouseListener
El usuario pasa el mouse sobre una componente MouseMotionListener
Una componente se hace visible ComponentListener
Una componente adquiere el foco del teclado FocusListener
Cambia la selección en una lista o tabla ListSelectionListener

Threads y Swing

Como regla general sólo un thread debe accesar una componente Swing, para lograr esto, la receta es que sólo el thread que atiende los eventos invoque los métodos de las componentes.

El siguiente código sigue el patrón "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 manipulación de la GUI -- setText, getText, etc.
//es efectuada por manejadores de eventos como actionPerformed().
...
}