5. Interfaces gráficas
Aquí nos proponemos mostrar cómo construir interfaces gráficas con JAVA. En primer lugar, veremos cuáles son las clases básicas que nos permiten crear una interfaz gráfica. En un primer momento, no utilizaremos ninguna herramienta de generación automática. Posteriormente, utilizaremos JBuilder, una herramienta de desarrollo de Borland/Inprise que facilita el desarrollo de aplicaciones Java y, en particular, la creación de interfaces gráficas.
5.1. Fundamentos de las interfaces gráficas
5.1.1. Una ventana sencilla
Consideremos el siguiente código:
// clases importadas
import javax.swing.*;
import java.awt.*;
// la clase formulario
public class form1 extends JFrame {
// el constructor
public form1() {
// título de la ventana
this.setTitle("Mon premier formulaire");
// dimensiones de la ventana
this.setSize(new Dimension(300,100));
}//constructor
// función de prueba
public static void main(String[] args) {
// se muestra el formulario
new form1().setVisible(true);
}
}//clase
Al ejecutar el código anterior, aparece la siguiente ventana:

Una interfaz gráfica suele derivarse de la clase base JFrame:
public class form1 extends JFrame {
La clase base JFrame define una ventana básica con botones para cerrarla, ampliarla o reducirla, un tamaño ajustable, etc., y gestiona los eventos de estos objetos gráficos. Aquí especializamos la clase base asignándole un título y su anchura (300 píxeles) y altura (100 píxeles). Esto se hace en su constructor:
// el constructor
public form1() {
// título de la ventana
this.setTitle("Mon premier formulaire");
// dimensiones de la ventana
this.setSize(new Dimension(300,100));
}//constructor
El título de la ventana se establece mediante el método setTitle y sus dimensiones mediante el método setSize. Este método acepta como parámetro un objeto Dimension(largeur,hauteur), donde largeur y hauteur son la anchura y la altura de la ventana, expresadas en píxeles.
El método main inicia la aplicación gráfica de la siguiente manera:
new form1().setVisible(true);
A continuación, se crea un formulario de tipo form1 (new form1()) y se muestra (setVisible(true)); después, la aplicación se pone a la escucha de los eventos que se producen en el formulario (clics, movimientos del ratón, ...) y ejecuta aquellos que el formulario gestiona. En este caso, nuestro formulario no gestiona otros eventos aparte de los que gestiona la clase base JFrame (clics en los botones de cierre, maximizar/minimizar, cambio de tamaño de la ventana, desplazamiento de la ventana, etc.).
Cuando se prueba este programa ejecutándolo desde una ventana de DOS mediante:
para ejecutar el archivo form1.class, se observa que, al cerrar la ventana que se ha mostrado, no se «recupera el control» en la ventana de DOS, como si el programa no hubiera finalizado. Y así es, efectivamente. La ejecución del programa se lleva a cabo de la siguiente manera:
- al principio, se inicia un primer hilo de ejecución para ejecutar el método main
- cuando este crea el formulario y lo muestra, se crea un segundo hilo para gestionar específicamente los eventos relacionados con el formulario
- tras esta creación y, en nuestro ejemplo, el hilo del método main finaliza y solo queda entonces el hilo de ejecución de la interfaz gráfica.
- Al cerrar la ventana, esta desaparece, pero no interrumpe el hilo en el que se estaba ejecutando
- Por el momento, nos vemos obligados a detener este hilo pulsando Ctrl+C en la ventana de DOS desde la que se inició la ejecución del programa.
Comprobemos la existencia de dos subprocesos separados: uno en el que se ejecuta el método main y otro en el que se ejecuta la ventana gráfica:
// clases importadas
import javax.swing.*;
import java.awt.*;
import java.io.*;
// la clase del formulario
public class form1 extends JFrame {
// el constructor
public form1() {
// título de la ventana
this.setTitle("Mon premier formulaire");
// dimensiones de la ventana
this.setSize(new Dimension(300,100));
}//constructor
// función de prueba
public static void main(String[] args) {
// seguimiento
System.out.println("Début du thread main");
// se muestra el formulario
new form1().setVisible(true);
// seguimiento
System.out.println("Fin du thread main");
}//principal
}//clase
La ejecución da los siguientes resultados:

Se puede observar que el hilo main ha finalizado, mientras que la ventana sigue abierta. El hecho de cerrar la ventana no detiene el hilo en el que se estaba ejecutando. Para detener este hilo, volvemos a pulsar Ctrl+C en la ventana de DOS.
Para concluir este ejemplo, cabe señalar los paquetes importados:
- javax.swing para la clase JFrame
- java.awt para la clase Dimension
5.1.2. Gestionar un evento
En el ejemplo anterior, tendríamos que gestionar nosotros mismos el cierre de la ventana para que, cuando se produzca, se detenga la aplicación, algo que por el momento no se hace. Para ello, debemos crear un objeto que «escuche» los eventos que se producen en la ventana y detecte el evento «cierre de la ventana». A este objeto se le denomina «listener» o gestor de eventos. Existen diferentes tipos de gestores para los distintos eventos que pueden producirse en los componentes de una interfaz gráfica. Para el componente JFrame, el listener se llama WindowListener y es una interfaz que define los siguientes métodos (véase la documentación de Java)
Resumen de métodos | ||
void | windowActivated(WindowEvent e) La ventana se convierte en la ventana activa | |
void | windowClosed(WindowEvent e) La ventana se ha cerrado | |
void | windowClosing(WindowEvent e) El usuario o el programa ha solicitado el cierre de la ventana | |
void | windowDeactivated(WindowEvent e) La ventana ya no es la ventana activa | |
void | windowDeiconified(WindowEvent e) La ventana pasa del estado minimizado al estado normal | |
void | windowIconified(WindowEvent e) La ventana pasa del estado normal al estado minimizado | |
void | windowOpened(WindowEvent e) La ventana se hace visible por primera vez | |
Por lo tanto, hay siete eventos que se pueden gestionar. Todos los controladores reciben como parámetro un objeto de tipo WindowEvent que, por el momento, ignoramos. El evento que nos interesa aquí es el cierre de la ventana, evento que deberá ser gestionado por el método windowClosing. Para gestionar este evento, podemos crear un objeto Windowlistener utilizando una clase anónima de la siguiente manera:
// creación de un gestor de eventos
WindowListener win=new WindowListener(){
public void windowActivated(WindowEvent e){}
public void windowClosed(WindowEvent e){}
public void windowClosing(WindowEvent e){System.exit(0);}
public void windowDeactivated(WindowEvent e){}
public void windowDeiconified(WindowEvent e){}
public void windowIconified(WindowEvent e){}
public void windowOpened(WindowEvent e){}
};//definición de Win
Nuestro gestor de eventos, que implementa la interfaz WindowListener, debe definir los siete métodos de dicha interfaz. Como solo queremos gestionar el cierre de la ventana, solo definimos código para el método windowClosing. Cuando se produzcan los demás eventos, se nos notificará, pero no haremos nada. ¿Qué haremos cuando se nos notifique que la ventana se está cerrando (windowClosing)? Detendremos la aplicación:
public void windowClosing(WindowEvent e){System.exit(0);}
Aquí tenemos un objeto capaz de gestionar los eventos de una ventana en general. ¿Cómo lo asociamos a una ventana concreta? La clase JFrame tiene un método addWindowListener(WindowListener win) que permite asociar un gestor de eventos de «ventana» a una ventana concreta. Así pues, aquí, en el constructor de la ventana, escribiremos:
// creación de un gestor de eventos
WindowListener win=new WindowListener(){
public void windowActivated(WindowEvent e){}
public void windowClosed(WindowEvent e){}
public void windowClosing(WindowEvent e){System.exit(0);}
public void windowDeactivated(WindowEvent e){}
public void windowDeiconified(WindowEvent e){}
public void windowIconified(WindowEvent e){}
public void windowOpened(WindowEvent e){}
};//definición de Windows
// Este gestor de eventos se encargará de gestionar los eventos de la ventana actual
this.addWindowListener(win);
El programa completo es el siguiente:
// clases importadas
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;
// la clase «formulario»
public class form2 extends JFrame {
// el constructor
public form2() {
// título de la ventana
this.setTitle("Mon premier formulaire");
// dimensiones de la ventana
this.setSize(new Dimension(300,100));
// creación de un gestor de eventos
WindowListener win=new WindowListener(){
public void windowActivated(WindowEvent e){}
public void windowClosed(WindowEvent e){}
public void windowClosing(WindowEvent e){System.exit(0);}
public void windowDeactivated(WindowEvent e){}
public void windowDeiconified(WindowEvent e){}
public void windowIconified(WindowEvent e){}
public void windowOpened(WindowEvent e){}
};//definición de Windows
// este gestor de eventos gestionará los eventos de la ventana actual
this.addWindowListener(win);
}//constructor
// función de prueba
public static void main(String[] args) {
// se muestra el formulario
new form2().setVisible(true);
}//main
}//clase
El paquete java.awt.event contiene la interfaz WindowListener. Al ejecutar este programa y cerrar la ventana que se ha mostrado, se observa en la ventana de DOS desde donde se ha iniciado el programa que este ha finalizado su ejecución, algo que antes no ocurría.
En nuestro programa, la creación del objeto encargado de gestionar los eventos de la ventana resulta un poco engorrosa, ya que nos vemos obligados a definir métodos incluso para eventos que no queremos gestionar. En este caso, en lugar de utilizar la interfaz WindowListener, podemos utilizar la clase WindowAdapter. Esta implementa la interfaz WindowListener, con siete métodos vacíos. Al derivar la clase WindowAdapter y redefinir únicamente los métodos que nos interesan, obtenemos el mismo resultado que con la interfaz WindowListener, pero sin necesidad de definir los métodos que no nos interesan. La secuencia
- definición del gestor de eventos
- asociación del gestor a la ventana
puede llevarse a cabo de la siguiente manera en nuestro ejemplo:
// creación de un gestor de eventos
WindowAdapter win=new WindowAdapter(){
public void windowClosing(WindowEvent e){System.exit(0);}
};//definición de Win
// este gestor de eventos gestionará los eventos de la ventana actual
this.addWindowListener(win);
Aquí utilizamos una clase anónima que deriva de la clase WindowAdapter y redefine su método windowClosing. El programa queda entonces así:
// clases importadas
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;
// la clase «formulario»
public class form2 extends JFrame {
// el constructor
public form2() {
// título de la ventana
this.setTitle("Mon premier formulaire");
// dimensiones de la ventana
this.setSize(new Dimension(300,100));
// creación de un gestor de eventos
WindowAdapter win=new WindowAdapter(){
public void windowClosing(WindowEvent e){System.exit(0);}
};//definición de Windows
// este gestor de eventos gestionará los eventos de la ventana actual
this.addWindowListener(win); }//constructor
// función de prueba
public static void main(String[] args) {
// se muestra el formulario
new form2().setVisible(true);
}//main
}//clase
Ofrece los mismos resultados que el programa anterior, pero es más sencillo de escribir.
5.1.3. Un formulario con un botón
Ahora añadamos un botón a nuestra ventana:
// clases importadas
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;
// la clase del formulario
public class form3 extends JFrame {
// un botón
JButton btnTest=null;
Container conteneur=null;
// el constructor
public form3() {
// título de la ventana
this.setTitle("Formulaire avec bouton");
// dimensiones de la ventana
this.setSize(new Dimension(300,100));
// creación de un gestor de eventos
WindowAdapter win=new WindowAdapter(){
public void windowClosing(WindowEvent e){System.exit(0);}
};//definición de Windows
// este gestor de eventos gestionará los eventos de la ventana actual
this.addWindowListener(win);
// se recupera el contenedor de la ventana
conteneur=this.getContentPane();
// se elige un gestor de maquetación de los componentes de este contenedor
conteneur.setLayout(new FlowLayout());
// se crea un botón
btnTest=new JButton();
// se establece su texto
btnTest.setText("Test");
// se añade el botón al contenedor
conteneur.add(btnTest);
}//constructor
// función de prueba
public static void main(String[] args) {
// se muestra el formulario
new form3().setVisible(true);
}//main
}//clase
Una ventana JFrame tiene un contenedor en el que se pueden colocar componentes gráficos (botones, casillas de selección, listas desplegables, etc.). Se puede acceder a este contenedor mediante el método getContentPane de la clase JFrame:
Container conteneur=null;
..........
// se recupera el contenedor de la ventana
conteneur=this.getContentPane();
Cada componente se coloca en el contenedor mediante el método add de la clase Container. Así, para colocar el componente C en el objeto conteneur anterior, se escribirá:
¿Dónde se coloca este componente en el contenedor? Existen varios gestores de disposición de componentes con el nombre XXXLayout, siendo XXX igual, por ejemplo, a Border, Flow, ... Cada gestor de disposición tiene sus propias características. Por ejemplo, el gestor FlowLayout dispone los componentes en línea, comenzando por la parte superior del formulario. Cuando se ha completado una línea, los componentes se colocan en la línea siguiente. Para asociar un gestor de formato a una ventana JFrame, se utiliza el método setLayout de la clase JFrame con la siguiente sintaxis:
Así, en nuestro ejemplo, para asociar un gestor de tipo FlowLayout a la ventana, hemos escrito:
// se selecciona un gestor de formato para los componentes de este contenedor
conteneur.setLayout(new FlowLayout());
Se puede prescindir del gestor de diseño y escribir:
En este caso, habrá que indicar las coordenadas exactas del componente en el contenedor en el formato (x, y, ancho, alto), donde (x, y) son las coordenadas de la esquina superior izquierda del componente en el contenedor. Este es el método que utilizaremos con mayor frecuencia a partir de ahora.
Ahora sabemos cómo se colocan los componentes en el contenedor (add) y dónde (setLayout). Solo nos queda conocer los
componentes que se pueden colocar en un contenedor. Aquí colocamos un botón modelado por la clase javax.swing.JButton:
JButton btnTest=null;
..........
// se crea un botón
btnTest=new JButton();
// se establece su texto
btnTest.setText("Test");
// se añade el botón al contenedor
conteneur.add(btnTest);
Al ejecutar este programa, aparece la siguiente ventana:

Si se cambia el tamaño del formulario anterior, se activa automáticamente el gestor de disposición del contenedor para reubicar los componentes:

Este es el principal interés de los gestores de disposición: mantener una disposición coherente de los componentes a medida que cambia el tamaño del contenedor. Utilicemos el gestor de disposición null para ver la diferencia. Ahora, el botón se coloca en el contenedor mediante las siguientes instrucciones:
// Se selecciona un gestor de formato de componentes en este contenedor
conteneur.setLayout(null);
// se crea un botón
btnTest=new JButton();
// se establece su texto
btnTest.setText("Test");
// se establece su ubicación y sus dimensiones
btnTest.setBounds(10,20,100,20);
// se añade el botón al contenedor
conteneur.add(btnTest);
Aquí colocamos explícitamente el botón en el punto (10,20) del formulario y fijamos sus dimensiones en 100 píxeles de ancho y 20 píxeles de alto. La nueva ventana queda así:

Si se cambia el tamaño de la ventana, el botón permanece en el mismo lugar.

Si hacemos clic en el botón Test, no ocurre nada. De hecho, aún no hemos asociado ningún controlador de eventos al botón. Para conocer el tipo de controladores de eventos disponibles para un componente determinado, podemos buscar en la definición de su clase los métodos addXXXListener que permiten asociar un controlador de eventos al componente. La clase javax.swing.JButton deriva de la clase javax.swing.AbstractButton, en la que se encuentran los siguientes métodos:
Resumen de métodos | ||
void | addActionListener(ActionListener l) | |
void | addChangeListener(ChangeListener l) | |
void | addItemListener(ItemListener l) | |
En este caso, hay que consultar la documentación para saber qué gestor de eventos se encarga del clic en el botón. Se trata de la interfaz ActionListener. Esta solo define un método:
Resumen de métodos | ||
void | actionPerformed(ActionEvent e) | |
El método recibe un parámetro ActionEvent que, por el momento, ignoraremos. Para gestionar el clic en el botón btntest de nuestro programa, primero le asignamos un gestor de eventos:
btnTest.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt){
btnTest_clic(evt);
}
}//clase anónima
);//gestor de eventos
Aquí, el método actionPerformed hace referencia al método btnTest_clic, que definimos de la siguiente manera:
public void btnTest_clic(ActionEvent evt){
// seguimiento de la consola
System.out.println("clic sur bouton");
}//btnTest_click
Cada vez que el usuario hace clic en el botón Test, se escribe un mensaje en la consola. Así lo muestra la siguiente ejecución:

El programa completo es el siguiente:
// clases importadas
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;
// la clase formulario
public class form4 extends JFrame {
// un botón
JButton btnTest=null;
Container conteneur=null;
// el constructor
public form4() {
// título de la ventana
this.setTitle("Formulaire avec bouton");
// dimensiones de la ventana
this.setSize(new Dimension(300,100));
// creación de un gestor de eventos
WindowAdapter win=new WindowAdapter(){
public void windowClosing(WindowEvent e){System.exit(0);}
};//definición de Windows
// este gestor de eventos gestionará los eventos de la ventana actual
this.addWindowListener(win);
// se recupera el contenedor de la ventana
conteneur=this.getContentPane();
// se elige un gestor de maquetación de los componentes de este contenedor
conteneur.setLayout(null);
// se crea un botón
btnTest=new JButton();
// se establece su texto
btnTest.setText("Test");
// se establece su ubicación y sus dimensiones
btnTest.setBounds(10,20,100,20);
// se le asocia un gestor de eventos
btnTest.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt){
btnTest_clic(evt);
}
}//clase anónima
);//gestor de eventos
// se añade el botón al contenedor
conteneur.add(btnTest);
}//constructor
public void btnTest_clic(ActionEvent evt){
// seguimiento de consola
System.out.println("clic sur bouton");
}//btnTest_click
// función de prueba
public static void main(String[] args) {
// se muestra el formulario
new form4().setVisible(true);
}//principal
}//clase
5.1.4. Los gestores de eventos
Los principales componentes de Swing que vamos a presentar son las ventanas (JFrame), los botones (JButton), las casillas de selección (JCheckBox), los botones de opción (JButtonRadio), los menús desplegables (JComboBox), las listas (JList), los controles deslizantes (JScrollBar), las etiquetas (JLabel), los campos de entrada de una línea (JTextField) o de varias líneas (JTextArea), los menús (JMenuBar), los elementos de menú (JMenuItem).
Las siguientes tablas recogen una lista de algunos gestores de eventos y los eventos a los que están vinculados.
Controlador | Componente(s) | Método de registro | Evento |
ActionListener | JButton, JCheckbox, JButtonRadio, JMenuItem | public void addActionListener(ActionListener) | clic en el botón, la casilla de verificación, el botón de opción o el elemento del menú |
JTextField | |||
ItemListener | JComboBox, JList | public void addItemListener(ItemListener) | El elemento seleccionado ha cambiado |
InputMethodListener | JTextField, JTextArea | public void addMethodInputListener(InputMethodListener) | El texto del campo de entrada ha cambiado o el cursor de entrada ha cambiado de posición |
CaretListener | JTextField, JTextArea | public void addcaretListener(CaretListener) | El cursor de entrada ha cambiado de posición |
AdjustmentListener | JScrollBar | public void addAdjustmentListener(AdjustmentListener) | El valor del variador ha cambiado |
MouseMotionListener | public void addMouseMotionListener(MouseMotionListener) | el ratón se ha movido | |
WindowListener | JFrame | public void addWindowlistener(WindowListener) | evento de ventana |
MouseListener | public void addMouselistener(MouseListener) | eventos del ratón (clic, entrada/salida del área de un componente, pulsación de botón, suelta) | |
FocusListener | public void addFocuslistener(FocusListener) | evento «focus» (ganado, perdido) | |
KeyListener | public void addKeylistener(KeyListener) | Evento de teclado (tecla pulsada, presionada, soltada) |
Componente | Método de registro de los controladores de eventos |
JButton | public void addActionListener(ActionListener) |
JCheckbox | public void addItemListener(ItemListener) |
JCheckboxMenuItem | public void addItemListener(ItemListener) |
JComboBox | public void addItemListener(ItemListener) public void addActionListener(ActionListener) |
Container | public void addContainerListener(ContainerListener) |
JComponent | public void addComponentListener(ComponentListener) public void addFocusListener(FocusListener) public void addKeyListener(KeyListener) public void addMouseListener(MouseListener) public void addMouseMotionListener(MouseMotionListener) |
JFrame | public void addWindowlistener(WindowListener) |
JList | public void addItemListener(ItemListener) |
JMenuItem | public void addActionListener(ActionListener) |
JPanel | como contenedor |
JScrollPane | como contenedor |
JScrollBar | public void addAdjustmentListener(AdjustmentListener) |
JTextComponent | public void addInputMethodListener(InputMethodListener) public void addCaretListener(CaretListener) |
JTextArea | como JTextComponent |
JTextField | como JTextComponent public void addActionListener(ActionListener) |
Todos los componentes, excepto los del tipo TextXXX, al derivarse de la clase JComponent, también poseen los métodos asociados a dicha clase.
5.1.5. Los métodos de los gestores de eventos
La siguiente tabla enumera los métodos que deben implementar los distintos gestores de eventos.
Interfaz | Métodos |
ActionListener | public void actionPerformed(ActionEvent) |
AdjustmentListener | public void adjustmentValueChanged(AdjustmentEvent) |
ComponentListener | public void componentHidden(ComponentEvent) public void componentMoved(ComponentEvent) public void componentResized(ComponentEvent) public void componentShown(ComponentEvent) |
ContainerListener | public void componentAdded(ContainerEvent) public void componentRemoved(ContainerEvent) |
FocusListener | public void focusGained(FocusEvent) public void focusLost(FocusEvent) |
ItemListener | public void itemStateChanged(ItemEvent) |
KeyListener | public void keyPressed(KeyEvent) public void keyReleased(KeyEvent) public void keyTyped(KeyEvent) |
MouseListener | public void mouseClicked(MouseEvent) public void mouseEntered(MouseEvent) public void mouseExited(MouseEvent) public void mousePressed(MouseEvent) public void mouseReleased(MouseEvent) |
MouseMotionListener | public void mouseDragged(MouseEvent) public void mouseMoved(MouseEvent) |
TextListener | public void textValueChanged(TextEvent) |
InputmethodListener | public void InputMethodTextChanged(InputMethodEvent) public void caretPositionChanged(InputMethodEvent) |
CaretLisetner | public void caretUpdate(CaretEvent) |
WindowListener | public void windowActivated(WindowEvent) public void windowClosed(WindowEvent) public void windowClosing(WindowEvent) public void windowDeactivated(WindowEvent) public void windowDeiconified(WindowEvent) public void windowIconified(WindowEvent) public void windowOpened(WindowEvent) |
5.1.6. Las clases adaptadoras
Como hemos visto en el caso de la interfaz WindowListener, existen clases denominadas XXXAdapter que implementan las interfaces XXXListener con métodos vacíos. Un gestor de eventos derivado de una clase XXXAdapter puede, por tanto, implementar solo una parte de los métodos de la interfaz XXXListener, concretamente aquellos que la aplicación necesite.
Supongamos que queremos gestionar los clics del ratón en un componente Frame f1. Podríamos asociarle un gestor de eventos mediante:
y escribir:
public class gestionnaireSouris implements MouseListener{
// se escriben los 5 métodos de la interfaz MouseListener
// mouseClicked, ..., mouseReleased)
}// fin de clase
Sin embargo, como solo queremos gestionar los clics del ratón, es preferible escribir:
public class gestionnaireSouris extends MouseAdapter{
// se escribe un único método, el que gestiona los clics del ratón
public void mouseClicked(MouseEvent evt){
…
}
}// fin de clase
La siguiente tabla muestra las clases adaptadoras de los distintos gestores de eventos:
Gestor de eventos | Adaptador |
ComponentListener | ComponentAdapter |
ContainerListener | ContainerAdapter |
FocusListener | FocusAdapter |
KeyListener | KeyAdapter |
MouseListener | MouseAdapter |
MouseMotionListener | MouseMotionAdapter |
WindowListener | WindowAdapter |
5.1.7. Conclusión
Acabamos de presentar los conceptos básicos de la creación de interfaces gráficas en Java:
- creación de una ventana
- creación de componentes
- asignación de los componentes a la ventana mediante un gestor de disposición
- asignación de gestores de eventos a los componentes
Ahora, en lugar de crear interfaces gráficas «a mano» como acabamos de hacer, vamos a utilizar JBuilder, una herramienta de desarrollo Java de Borland/Inprise en su versión 4, y supérieure.Nous utilizaremos los componentes de la biblioteca java.swing, recomendada actualmente por Sun, creador de Java.
5.2. Creación de una interfaz gráfica con JBuilder
5.2.1. Nuestro primer proyecto con JBuilder
Para familiarizarnos con JBuilder, vamos a crear una aplicación muy sencilla: una ventana vacía.
- Inicia JBuilder y selecciona la opción Archivo/Nuevo proyecto. A continuación, aparecerá la primera página de un asistente:

- Rellena los siguientes campos:
Nombre del proyecto | Inicio Esto provocará la creación de un archivo de proyecto début.jpr en la carpeta indicada en el campo «Nombre del directorio del proyecto» |
Ruta raíz | Indica la carpeta en la que se creará la carpeta del proyecto que vas a crear. |
Nombre del directorio del proyecto | Indica el nombre de la carpeta donde se guardarán todos los archivos del proyecto. Esta carpeta se creará en el directorio indicado en el campo «Ruta raíz» |
Los archivos de origen (.java, .html, ...), los archivos de destino (.class, ...) y los archivos de copia de seguridad podrían guardarse en directorios diferentes. Si deja estos campos en blanco, se colocarán en el mismo directorio que el proyecto.
Escriba [suivant]
- Aparecerá una pantalla que confirmará las opciones seleccionadas en el paso anterior

Seleccione [suivant]
- Aparecerá una nueva pantalla en la que se le pedirá que defina su proyecto:

Seleccione [terminer]
- Comprueba que la opción Voir/projet esté marcada. Deberías ver la estructura de tu proyecto en la ventana de la izquierda.

- Ahora vamos a crear una interfaz gráfica en este proyecto. Selecciona la opción Fichier/Nouveau/Application:

En el campo classe, se introduce el nombre de la clase que se va a crear. Aquí hemos utilizado el mismo nombre que el del proyecto.
Selecciona [suivant]
- Aparecerá la siguiente pantalla:

Clase | interfaceDébut Es el nombre de la clase correspondiente a la ventana que se va a crear |
Título | Es el texto que aparecerá en la barra de título de la ventana |
Ten en cuenta que, en el ejemplo anterior, hemos indicado que la ventana se centre en la pantalla al iniciar la aplicación.
Escriba [Terminer]
- Ahora es cuando JBuilder resulta útil.
- Genera los archivos fuente .java de las dos clases cuyos nombres hemos indicado: la clase de la aplicación y la de la interfaz gráfica. Estos dos archivos aparecen en la estructura del proyecto, en la ventana de la izquierda

- Para acceder al código generado para ambas clases, basta con hacer doble clic en el archivo .java correspondiente. Volveremos más adelante sobre el código generado.
- Comprueba que la opción Voir/Structure esté marcada. Permite ver la estructura de la clase seleccionada actualmente (haciendo doble clic en el archivo .java). A continuación se muestra, por ejemplo, la estructura de la clase début:

Aquí se puede ver:
-
las bibliotecas importadas (imports)
-
que hay un constructor début()
-
que hay un método estático main()
-
que hay un atributo packFrame
¿Para qué sirve tener acceso a la estructura de una clase?
-
Te ofrece una visión general de la misma. Esto resulta útil si tu clase es compleja.
-
Puedes acceder al código de un método haciendo clic sobre él en la ventana de estructura de la clase. De nuevo, esto resulta útil si tu clase tiene cientos de líneas. No tienes que revisar todas las líneas para encontrar el código que buscas.
El código generado por JBuilder ya está listo para su uso. Selecciona Ejecutar/Ejecutar el proyecto o F9 y aparecerá la ventana solicitada:

Además, se cierra correctamente al hacer clic en el botón de cierre de la ventana. Acabamos de crear nuestra primera interfaz gráfica. Podemos guardar nuestro proyecto mediante la opción Archivo/Cerrar proyectos:

Al pulsar Tous, se marcarán todos los proyectos presentes en la ventana anterior. OK los cerrará. Si tenemos curiosidad por ir, con el Explorador de Windows, a la carpeta de nuestro proyecto (la que se indicó al asistente al inicio de la configuración del proyecto), encontraremos allí los siguientes archivos:

En nuestro ejemplo, habíamos solicitado que todos los archivos (fuente .java, destino .class, copia de seguridad .jpr~) estuvieran en la misma carpeta que el proyecto .jpr.
5.2.2. Los archivos generados por JBuilder para una interfaz gráfica
Ahora vamos a echar un vistazo a los archivos fuente .java que ha generado JBuilder. Es importante saber interpretar lo que se genera, ya que la mayoría de las veces tendremos que añadir código a lo que se ha generado. Empecemos por recuperar nuestro proyecto: Archivo/Abrir un proyecto y seleccionemos el proyecto début.jpr. Encontramos el proyecto creado anteriormente.
5.2.2.1. La clase principal
Examinemos la clase début.java haciendo doble clic en su nombre en la ventana que muestra la lista de archivos del proyecto. Tenemos el siguiente código:
import javax.swing.UIManager;
import java.awt.*;
public class début {
boolean packFrame = false;
/**Compilar la aplicación*/
public début() {
interfaceDébut frame = new interfaceDébut();
//Validar los marcos con tamaños predefinidos
//Ajustar los marcos con información de tamaño preferido —por ejemplo, según su disposición—
if (packFrame) {
frame.pack();
}
else {
frame.validate();
}
//Centrar la ventana
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = frame.getSize();
if (frameSize.height > screenSize.height) {
frameSize.height = screenSize.height;
}
if (frameSize.width > screenSize.width) {
frameSize.width = screenSize.width;
}
frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);
frame.setVisible(true);
}
/**Método principal*/
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e) {
e.printStackTrace();
}
new début();
}
}
Comentemos el código generado:
- la función main establece el aspecto de la ventana (setLookAndFeel) y crea una instancia de la clase début.
- A continuación, se ejecuta el constructor début(). Este crea una instancia frame de la clase de la ventana (new interfaceDébut()). Dicha instancia se crea, pero no se muestra.
- A continuación, la ventana se dimensiona según la información disponible para cada uno de sus componentes (frame.validate). Entonces comienza su existencia independiente mostrándose en pantalla y respondiendo a las acciones del usuario.
- La ventana se centra en la pantalla, ya que así se solicitó al configurarla con el asistente.
Veamos qué se obtendría si redujéramos el código début.java a lo estrictamente necesario, tal y como hicimos al principio del capítulo. Creemos una nueva clase. Selecciona la opción Archivo/Nueva clase:

Asigna a la nueva clase el nombre début2 y cambia [Terminer]. Aparecerá un nuevo archivo en el proyecto:

El archivo début2.java se reduce a su forma más simple:
Completemos la clase de la siguiente manera:
public class début2 {
// función principal
public static void main(String args[]){
// crea la ventana
new interfaceDébut().show(); // o new interfaceDébut.setVisible(true);
}//main
}//clase inicio2
La función main crea una instancia de la ventana interfaceDébut y la muestra (show). Antes de ejecutar nuestro proyecto, debemos señalar que la clase que contiene la función main que se va a ejecutar es ahora la clase début2. Haga clic con el botón derecho del ratón sobre el proyecto début.jpr y seleccione la opción propriétés y, a continuación, la pestaña Exécution:
21

Aquí se indica que la clase principal es début (1). Pulsa el botón (2) para seleccionar otra clase principal:

Seleccione début2 y cambie [OK].

Seleccione [OK] para confirmar esta elección y, a continuación, solicite la ejecución del proyecto mediante Ejecutar/Ejecutar proyecto o F9. Aparecerá la misma ventana que con la clase début, salvo que no está centrada, ya que en este caso no se ha solicitado. A partir de ahora, ya no presentaremos la clase principal generada por JBuilder, ya que siempre hace lo mismo: crear una ventana. A partir de ahora nos centraremos en la clase de esta última.
5.2.2.2. La clase de la ventana
Veamos ahora el código que se ha generado para la clase interfaceDébut:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class interfaceDébut extends JFrame {
JPanel contentPane;
BorderLayout borderLayout1 = new BorderLayout();
/**Crear el marco*/
public interfaceDébut() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar el componente*/
private void jbInit() throws Exception {
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(borderLayout1);
this.setSize(new Dimension(400, 300));
this.setTitle("Ma première interface graphique avec Jbuilder");
}
/**Sustituido, para que podamos salir cuando se cierre la ventana*/
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
}
5.2.2.2.1. Las bibliotecas importadas
Se trata de las bibliotecas java.awt, java.awt.event y javax.swing. Las dos primeras eran las únicas disponibles para crear interfaces gráficas con las primeras versiones de Java. La biblioteca javax.swing es más reciente. En este caso, es necesaria para la ventana de tipo JFrame que se utiliza aquí.
5.2.2.2.2. Los atributos
JPanel es un tipo de contenedor en el que se pueden colocar componentes. BorderLayout es uno de los tipos de gestores de diseño disponibles para colocar los componentes en el contenedor. En todos nuestros ejemplos, no utilizaremos ningún gestor de formato y colocaremos nosotros mismos los componentes en un lugar concreto del contenedor. Para ello, utilizaremos el gestor de formato null.
5.2.2.2.3. El generador de la ventana
/**Crear el marco*/
public interfaceDébut() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar el componente*/
private void jbInit() throws Exception {
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(borderLayout1);
this.setSize(new Dimension(400, 300));
this.setTitle("Ma première interface graphique avec Jbuilder");
}
- El desarrollador comienza diciendo que va a gestionar los eventos de la ventana (enableEvents) y, a continuación, ejecuta el método jbInit.
- Se obtiene (getContentPane) el contenedor (JPanel) de la ventana (JFrame)
- Se establece el gestor de formato (setLayout)
- Se establece el tamaño de la ventana (setSize)
- Se establece el título de la ventana (setTitle)
5.2.2.2.4. El gestor de eventos
/**Sustituido, para que podamos salir cuando se cierre la ventana*/
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
El desarrollador había indicado que la clase se encargaría de gestionar los eventos de la ventana. El método processWindowEvent es el que realiza esta tarea. Comienza por transmitir a su clase padre (JFrame) el evento WindowEvent recibido y, a continuación, si este es el evento WINDOW_CLOSING provocado al hacer clic en el botón de cierre de la ventana, la aplicación se detiene.
5.2.2.2.5. Conclusión
El código de la clase de la ventana es diferente al presentado en el ejemplo del principio del capítulo. Si utilizáramos otra herramienta de generación de código Java distinta de JBuilder, sin duda tendríamos un código aún más diferente. En la práctica, aceptaremos el código generado por JBuilder para crear la ventana, con el fin de centrarnos únicamente en escribir los controladores de eventos de la interfaz gráfica.
5.2.3. Diseñar una interfaz gráfica
5.2.3.1. Un ejemplo
En el ejemplo anterior, no habíamos incluido ningún componente en la ventana. Ahora vamos a crear una ventana con un botón, un cuadro de texto y un campo de entrada:

Los campos son los siguientes:
n.º | nombre | tipo | función |
1 | lblSaisie | JLabel | una denominación |
2 | txtSaisie | JTextField | un campo de entrada |
3 | cmdAfficher | JButton | para mostrar en un cuadro de diálogo el contenido del campo de entrada txtSaisie |
Siguiendo los mismos pasos que en el proyecto anterior, crea el proyecto interface2.jpr sin añadir por el momento ningún componente a la ventana.

En la ventana anterior, selecciona la clase interface2.java de la ventana. A la derecha de esta ventana hay un archivador con pestañas:

La pestaña Source da acceso al código fuente de la clase interface2.java. La pestaña Conception permite diseñar visualmente la ventana. Selecciona esta pestaña. Tienes ante ti el contenedor de la ventana, que albergará los componentes que vayas colocando en él. Por el momento está vacío. En la ventana de la izquierda se muestra la estructura de la clase:

this | representa la ventana |
contentPane | su contenedor, en el que se van a colocar los componentes, así como la forma en que se van a disponer dichos componentes en el contenedor (BorderLayout por defecto) |
borderLayout1 | una instancia del gestor de formato |
Seleccione el objeto this. A continuación, aparecerá su ventana de propiedades a la derecha:

Cabe destacar algunas de estas propiedades:
background | para establecer el color de fondo de la ventana |
foreground | para establecer el color de los elementos gráficos de la ventana |
JMenuBar | para asociar un menú a la ventana |
title | para asignar un título a la ventana |
resizable | para establecer el tipo de ventana |
font | para establecer la fuente de los textos de la ventana |
Con el objeto this aún seleccionado, se puede cambiar el tamaño del contenedor que se muestra en pantalla arrastrando los puntos de anclaje situados alrededor del contenedor:

Ahora ya estamos listos para colocar componentes en el contenedor anterior. Antes de eso, vamos a cambiar el gestor de formato. Selecciona el objeto contentPane en la ventana de estructura:

A continuación, en la ventana de propiedades de este objeto, selecciona la propiedad layout y elige, entre los valores posibles, el valor null:

La ausencia de un gestor de formato nos permitirá colocar libremente los componentes en el contenedor. Ahora es el momento de seleccionarlos.
Cuando se selecciona el panel Conception, los componentes están disponibles en una carpeta con pestañas situada en la parte superior de la ventana de diseño:

Para crear la interfaz gráfica, disponemos de componentes swing (1) y de componentes awt (2). En este caso, vamos a utilizar los componentes swing. En la barra de componentes situada arriba, selecciona un componente JLabel (3), un componente JTextField (4) y un componente JButton (5), y colócalos en el contenedor de la ventana de diseño.

Ahora personalicemos cada uno de estos tres componentes:
- la etiqueta (JLabel) jLabel1
Selecciona el componente para abrir su ventana de propiedades. En ella, modifica las siguientes propiedades: nombre: lblSaisie, texto: Introducción
- el campo de entrada (JTextField) jTextfield1
Selecciona el componente para abrir su ventana de propiedades. En ella, modifica las siguientes propiedades: name: txtSaisie, text: no introducir nada
- el botón (JButton): nombre: cmdAfficher, texto: Mostrar
Ahora tenemos la siguiente ventana:

y la siguiente estructura:

Podemos ejecutar (F9) nuestro proyecto para obtener una primera vista previa de la ventana en funcionamiento:

Cierra la ventana. Ahora nos queda escribir el procedimiento asociado al clic en el botón Afficher. Selecciona el botón para acceder a su ventana de propiedades. Esta tiene dos pestañas: propriétés y événements. Seleccione événements.

La columna de la izquierda de la ventana muestra los eventos posibles del botón. Al hacer clic en un botón se produce el evento actionPerformed. La columna de la derecha contiene el nombre del procedimiento que se invoca cuando se produce el evento correspondiente. Haz clic en la celda situada a la derecha del evento actionPerformed:

JBuilder genera un nombre por defecto para cada gestor de eventos con el formato nomComposant_nomEvénement; en este caso, cmdAfficher_actionPerformed. Se podría borrar el nombre predeterminado y escribir otro. Para acceder al código del controlador cmdAfficher_actionPerformed, basta con hacer doble clic en su nombre, tal y como se muestra arriba. De este modo, se pasa automáticamente al panel de código fuente de la clase, situado en el esqueleto del código del controlador de eventos:
Ahora solo nos queda completar este código. En este caso, queremos mostrar un cuadro de diálogo con el contenido del campo txtSaisie:
void cmdAfficher_actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(this, "texte saisi="+txtSaisie.getText(),
"Vérification de la saisie",JOptionPane.INFORMATION_MESSAGE);
}
JOptionPane es una clase de la biblioteca javax.swing. Permite mostrar mensajes acompañados de un icono o solicitar información al usuario. En este caso, utilizamos un método estático de la clase:

parentComponent | el objeto contenedor «padre» del cuadro de diálogo: en este caso, this. |
mensaje | un objeto que se va a mostrar. En este caso, el contenido del campo de entrada |
título | el título del cuadro de diálogo |
messageType | el tipo de mensaje que se va a mostrar. Determina el icono que aparecerá en el cuadro junto al mensaje. Los valores posibles son: INFORMATION_MESSAGE, QUESTION_MESSAGE, ERROR_MESSAGE, WARNING_MESSAGE, PLAIN_MESSAGE |
Ejecutemos nuestra aplicación (F9):


5.2.3.2. El código de la clase de la ventana
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.beans.*;
import javax.swing.event.*;
public class interface2 extends JFrame {
JPanel contentPane;
JLabel lblSaisie = new JLabel();
JTextField txtSaisie = new JTextField();
JButton cmdAfficher = new JButton();
/**Crear el marco*/
public interface2() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar el componente*/
private void jbInit() throws Exception {
lblSaisie.setText("Saisie");
lblSaisie.setBounds(new Rectangle(25, 23, 71, 21));
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(null);
this.setSize(new Dimension(304, 129));
this.setTitle("Saisies & boutons - 1");
txtSaisie.setBounds(new Rectangle(120, 21, 138, 24));
cmdAfficher.setText("Afficher");
cmdAfficher.setBounds(new Rectangle(111, 77, 77, 20));
cmdAfficher.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdAfficher_actionPerformed(e);
}
});
contentPane.add(lblSaisie, null);
contentPane.add(txtSaisie, null);
contentPane.add(cmdAfficher, null);
}
/**Sustituido, para que podamos salir cuando se cierre la ventana*/
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
void cmdAfficher_actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(this, "texte saisi="+txtSaisie.getText(), "Vérification de la saisie",JOptionPane.INFORMATION_MESSAGE);
}
}
5.2.3.2.1. Los atributos
JPanel contentPane;
JLabel lblSaisie = new JLabel();
JTextField txtSaisie = new JTextField();
JButton cmdAfficher = new JButton();
Encontramos el contenedor de los componentes del tipo JPanel y los tres componentes.
5.2.3.2.2. El fabricante
/**Crear el marco*/
public interface2() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar el componente*/
private void jbInit() throws Exception {
lblSaisie.setText("Saisie");
lblSaisie.setBounds(new Rectangle(25, 23, 71, 21));
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(null);
this.setSize(new Dimension(304, 129));
this.setTitle("Saisies & boutons - 1");
txtSaisie.setBounds(new Rectangle(120, 21, 138, 24));
cmdAfficher.setText("Afficher");
cmdAfficher.setBounds(new Rectangle(111, 77, 77, 20));
cmdAfficher.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdAfficher_actionPerformed(e);
}
});
contentPane.add(lblSaisie, null);
contentPane.add(txtSaisie, null);
contentPane.add(cmdAfficher, null);
}
El constructor interface2 es similar al constructor de la interfaz gráfica anterior que hemos estudiado. Las diferencias se encuentran en el método jbInit: el código de construcción de la ventana depende de los componentes que se hayan colocado en ella. Podemos retomar el código de jbInit añadiendo nuestros propios comentarios:
private void jbInit() throws Exception {
// la propia ventana (tamaño, título)
this.setSize(new Dimension(304, 129));
this.setTitle("Saisies & boutons - 1");
// el contenedor de los componentes
contentPane = (JPanel) this.getContentPane();
// no hay gestor de formato para este contenedor
contentPane.setLayout(null);
// la etiqueta lblSaisie (texto, posición, tamaño)
lblSaisie.setText("Saisie");
lblSaisie.setBounds(new Rectangle(25, 23, 71, 21));
// el campo de entrada (posición, tamaño)
txtSaisie.setBounds(new Rectangle(120, 21, 138, 24));
// el botón «Mostrar» (texto, posición, tamaño)
cmdAfficher.setText("Afficher");
cmdAfficher.setBounds(new Rectangle(111, 77, 77, 20));
// el gestor de eventos del botón
cmdAfficher.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdAfficher_actionPerformed(e);
}
});
// Añadir los tres componentes al contenedor
contentPane.add(lblSaisie, null);
contentPane.add(txtSaisie, null);
contentPane.add(cmdAfficher, null);
}//jbInit
Cabe destacar dos cosas:
- este código podría haberse escrito a mano. Esto significa que se puede prescindir de JBuilder para crear una interfaz gráfica.
- la forma en que se establece el gestor de eventos del botón cmdAfficher. El gestor de eventos del componente cmdAfficher podría haberse declarado mediante cmdAfficher.addActionListener(new gestor()) donde gestionnaire sería una clase con un método público actionPerformed encargado de gestionar el clic en el botón Afficher. En este caso, JBuilder utiliza como gestor una instancia de una clase anónima:
new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdAfficher_actionPerformed(e);
}
Se crea una nueva instancia de la interfaz ActionListener y, a continuación, se define su método actionPerformed. Este método se limita a llamar a un método de la clase interface2. Todo esto no es más que un recurso para definir, en la misma clase que la ventana, los procedimientos de gestión de eventos de los componentes de dicha ventana. Se podría proceder de otra manera:
lo que hace que el método actionPerformed se busque en this, es decir, en la clase de la ventana. Este segundo método parece más sencillo, pero el primero tiene una ventaja: permite tener diferentes gestores para diferentes botones, mientras que el segundo método no lo permite. En este último caso, de hecho, el único método actionPeformed debe gestionar los clics de diferentes botones y, por lo tanto, debe empezar por identificar cuál es el origen del evento antes de comenzar a funcionar.
5.2.3.2.3. Los controladores de eventos
Nos encontramos con los que ya hemos estudiado:
/**Sustituido, para que podamos salir cuando se cierre la ventana*/
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
// clic en el botón «Mostrar»
void cmdAfficher_actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(this, "texte saisi="+txtSaisie.getText(), "Vérification de la saisie",JOptionPane.INFORMATION_MESSAGE);
}
5.2.3.3. Conclusion
A partir de los dos proyectos analizados, podemos concluir que, una vez creada la interfaz gráfica con JBuilder, el trabajo del desarrollador consiste en escribir los controladores de eventos que desea gestionar para dicha interfaz gráfica.
5.2.4. Buscar ayuda
Con Java, a menudo se necesita ayuda, sobre todo debido al gran número de clases disponibles. A continuación ofrecemos algunas indicaciones para encontrar ayuda sobre una clase. Selecciona la opción Ayuda/Temas de ayuda del menú.

La pantalla de ayuda suele tener dos ventanas:
- la de la izquierda, donde se indica lo que se busca. Tiene tres pestañas: Sommaire, Index y Chercher.
- la de la derecha, que muestra el resultado de la búsqueda
Hay disponible una guía sobre cómo utilizar la ayuda de JBuilder. Selecciona en la ayuda de JBuilder la opción Ayuda/Uso de la ayuda. Allí se explica cómo utilizar la ayuda. Por ejemplo, se indican los diferentes componentes del visor de ayuda:

Examinemos con más detalle las páginas Sommaire y Index.
5.2.4.1. Ayuda: Índice

5.2.4.1.1. Índice: Introducción a Java
Aquí se pueden encontrar los conceptos básicos de Java, pero no solo eso, tal y como muestra la lista de temas tratados en esta opción:

5.2.4.1.2. Índice: Tutoriales
Si seleccionamos la opción «Tutoriales» en el índice anterior, la ventana de la derecha nos muestra una lista de los tutoriales disponibles:

Los tutoriales básicos resultan especialmente interesantes para empezar a familiarizarse con JBuilder. Existen muchos otros además de los presentados anteriormente y, cuando se quiera desarrollar una aplicación, puede resultar útil comprobar antes si hay algún tutorial que pueda ayudarnos.
5.2.4.1.3. Índice: el JDK
Al seleccionar la opción Java 2 JDK 1.3, se tiene acceso a todas las bibliotecas de JDK. Por lo general, no es aquí donde hay que buscar si necesitamos información sobre una clase concreta y no sabemos en qué biblioteca se encuentra. Sin embargo, esta opción resulta útil si nos interesa tener una visión general de las bibliotecas de Java.
5.2.4.2. Ayuda: Índice
Selecciona la pestaña Índice de la ventana de la izquierda en la ayuda. Esta opción te permite, por ejemplo, encontrar ayuda sobre una clase. Supongamos, por ejemplo, que quieres conocer los métodos de los campos de entrada swing y JTextField. Escriba JTextField en el campo de búsqueda:
![]()
La ayuda mostrará las entradas del índice que comienzan por el texto introducido:

Ahora solo tienes que hacer doble clic en la entrada que te interese, en este caso JTextField class. La ayuda sobre esta clase se mostrará entonces en la ventana de la derecha:

A continuación, se te ofrece una descripción completa de la clase.
5.2.5. Algunos componentes de Swing
A continuación, presentamos diversas aplicaciones en las que se utilizan los componentes swing más habituales, con el fin de descubrir sus principales métodos y propiedades. Para cada aplicación, mostramos la interfaz gráfica y el código relevante, en particular el de los gestores de eventos.
5.2.5.1. Componentes JLabel y JTextField
Ya hemos visto estos dos componentes. JLabel es un componente de texto y JTextField, un componente de campo de entrada. Sus dos métodos principales son
String getText() | para obtener el contenido del campo de entrada o el texto de la etiqueta |
void setText(String unTexte) | para introducir unTexte en el campo o en la etiqueta |
Los eventos que se suelen utilizar para JTextField son los siguientes:
actionPerformed | indica que el usuario ha validado (tecla Intro) el texto introducido |
caretUpdate | indica que el usuario ha movido el cursor de introducción |
inputMethodChanged | indica que el usuario ha modificado el campo de entrada |
A continuación se muestra un ejemplo que utiliza el evento caretUpdate para realizar un seguimiento de los cambios en un campo de entrada:

n.º | tipo | nombre | función |
1 | JTextField | txtSaisie | campo de entrada |
2 | JTextField | txtControle | muestra el texto de 1 en tiempo real |
3 | JButton | cmdEffacer | para borrar los campos 1 y 2 |
4 | JButton | cmdQuitter | para salir de la aplicación |
El código correspondiente a esta aplicación es el siguiente:
import java.awt.*;
....
public class Cadre1 extends JFrame {
JPanel contentPane;
JTextField txtSaisie = new JTextField();
JLabel jLabel1 = new JLabel();
JLabel jLabel2 = new JLabel();
JTextField txtControle = new JTextField();
JButton CmdEffacer = new JButton();
JButton CmdQuitter = new JButton();
/**Crear el marco*/
public Cadre1() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar el componente*/
private void jbInit() throws Exception {
....
txtSaisie.addCaretListener(new javax.swing.event.CaretListener() {
public void caretUpdate(CaretEvent e) {
txtSaisie_caretUpdate(e);
}
});
...
CmdEffacer.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
CmdEffacer_actionPerformed(e);
}
});
...
CmdQuitter.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
CmdQuitter_actionPerformed(e);
}
});
....
}
/**Sustituido, para que podamos salir cuando se cierre la ventana*/
protected void processWindowEvent(WindowEvent e) {
...
}
void txtSaisie_caretUpdate(CaretEvent e) {
// el cursor de entrada se ha movido
txtControle.setText(txtSaisie.getText());
}
void CmdQuitter_actionPerformed(ActionEvent e) {
// Salimos de la aplicación
System.exit(0);
}
void CmdEffacer_actionPerformed(ActionEvent e) {
// Se borra el contenido del campo de entrada
txtSaisie.setText("");
}
}
A continuación se muestra un ejemplo de ejecución:

5.2.5.2. componente JComboBox


Un componente JComboBox es una lista desplegable acompañada de un campo de entrada: el usuario puede elegir un elemento en (2) o escribir texto en (1). Por defecto, los JComboBox no son editables. Para que sean editables, hay que llamar explícitamente al método setEditable(true). Para obtener más información sobre la clase JComboBox, escribe JComboBox en el índice de la ayuda.
El objeto JComboBox se puede crear de diferentes maneras:
new JComboBox() | crea un cuadro combinado vacío |
new JComboBox (Object[] items) | crea un cuadro combinado que contiene una matriz de objetos |
new JComboBox(Vector items) | lo mismo con un vector de objetos |
Puede sorprender que un combo pueda contener objetos, cuando normalmente contiene cadenas de caracteres. A nivel visual, así será. Si un JComboBox contiene un objeto obj, muestra la cadena obj.toString(). Recordemos que todo objeto tiene un método toString heredado de la clase Object, que devuelve una cadena de caracteres «representativa» del objeto.
Los métodos útiles de la clase JCombobox son los siguientes:
void addItem(Object unObjet) | añade un objeto al cuadro combinado |
int getItemCount() | devuelve el número de elementos del cuadro combinado |
Object getItemAt(int i) | devuelve el objeto n.º i del menú desplegable |
void insertItemAt(Object unObjet, int i) | inserta unObjet en la posición i del combo |
int getSelectedIndex() | devuelve el número del elemento seleccionado en el menú desplegable |
Object getSelectedItem() | devuelve el objeto seleccionado en el menú desplegable |
void setSelectedIndex(int i) | selecciona el elemento i del menú desplegable |
void setSelectedItem(Object unObjet) | selecciona el objeto especificado en el menú desplegable |
void removeAllItems() | vacía el menú desplegable |
void removeItemAt(int i) | elimina el elemento n.º i del cuadro combinado |
void removeItem(Object unObjet) | elimina el objeto especificado del cuadro combinado |
void setEditable(boolean val) | hace que el cuadro combinado sea editable (val=true) o no (val=false) |
Al seleccionar un elemento de la lista desplegable se produce el evento actionPerformed, que puede utilizarse para recibir una notificación del cambio de selección en el cuadro combinado. En la siguiente aplicación, utilizamos este evento para mostrar el elemento que se ha seleccionado en la lista.

Solo mostramos el código relevante de la ventana.
public class Cadre1 extends JFrame {
JPanel contentPane;
JComboBox jComboBox1 = new JComboBox();
JLabel jLabel1 = new JLabel();
/**Crear el cuadro*/
public Cadre1() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
// procesamiento: se rellena el menú desplegable
String[] infos={"un","deux","trois","quatre"};
for(int i=0;i<infos.length;i++)
jComboBox1.addItem(infos[i]);
}
/**Inicializar el componente*/
private void jbInit() throws Exception {
....
jComboBox1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
jComboBox1_actionPerformed(e);
}
});
....
}
void jComboBox1_actionPerformed(ActionEvent e) {
// Se ha seleccionado un nuevo elemento: se muestra
JOptionPane.showMessageDialog(this,jComboBox1.getSelectedItem(),
"actionPerformed",JOptionPane.INFORMATION_MESSAGE);
}
}
5.2.5.3. Componente JList
El componente Swing JList es más complejo que su homólogo de la biblioteca awt. Hay dos diferencias importantes:
- el contenido de la lista lo gestiona un objeto distinto de la propia lista. En este caso utilizaremos un objeto DefaultListModel, que se emplea como un Vector, pero que, además, avisa al objeto JList en cuanto cambia su contenido, para que la visualización de la lista también cambie.
- La lista no se desplaza de forma predeterminada. Es necesario colocar la lista en un contenedor ScrollPane, que sí permite dicho desplazamiento.
En el código fuente, la definición de una lista se puede realizar de la siguiente manera:
// el vector de valores de la lista
DefaultlistModel valeurs=new DefaultListModel();
// la propia lista a la que se asocia el vector de sus valores
JList jList1 = new JList(valeurs);
// el contenedor desplazable en el que se coloca la lista para obtener una lista desplazable
JScrollPane jScrollPane1 = new JScrollPane(jList1);
Para incluir la lista jList1 en el contenedor jScrollPane1, el código generado por JBuilder procede de forma diferente:
- declaración del contenedor en los atributos de la ventana
- y, a continuación, en el código de jbInit, la lista se asocia al contenedor
Para añadir valores a la lista JList1 anterior, basta con añadirlos a su vector de valores valeurs:
y se obtiene entonces la siguiente ventana:

¿Cómo se construye esta interfaz?
- Se selecciona un componente JScrollPane en la página «Contenedores Swing» de los componentes y se arrastra a la ventana, ajustando su tamaño al deseado
- Se selecciona un componente JList en la página «Swing» de los componentes y se coloca en el contenedor JScrollPane, donde ocupa todo el espacio.
El código generado por JBuilder debe modificarse ligeramente para obtener el siguiente código:
public class interfaceAppli extends JFrame {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
DefaultListModel valeurs=new DefaultListModel();
JList jList1 = new JList(valeurs);
JScrollPane jScrollPane1 = new JScrollPane();
JLabel jLabel2 = new JLabel();
/**Crear el marco*/
public interfaceAppli() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
// procesamiento
// se incluye la lista en el scrollPane
// inicialización de la lista
for(int i=0;i<10;i++)
valeurs.addElement(""+i);
}
/**Inicializar el componente*/
private void jbInit() throws Exception {
....
// la lista jList1 está asociada al contenedor jcrollPane1
jScrollPane1.getViewport().add(jList1, null);
}
/**Sustituido, así podemos salir cuando se cierre la ventana*/
protected void processWindowEvent(WindowEvent e) {
....
}
}
Veamos ahora los métodos principales de la clase JList buscando JList en el índice de la ayuda. El objeto JList se puede crear de diferentes maneras:

Un método sencillo es el que hemos utilizado: crear un DefaultListModel V vacío y, a continuación, asociarlo a la lista que se va a crear mediante new JList(V). El contenido de la lista no lo gestiona el objeto JList, sino el objeto que contiene los valores de la lista. Si el contenido se ha creado mediante un objeto DefaultListModel basado en la clase Vector, se podrán utilizar los métodos de la clase Vector para añadir, insertar y eliminar elementos de la lista. Una lista puede ser de selección simple o múltiple. Esto se establece mediante el método setSelectionMode:

Se puede conocer el modo de selección actual con getSelectionMode:
![]()
El elemento o los elementos seleccionados se pueden obtener mediante los siguientes métodos:

Sabemos cómo asociar un vector de valores a una lista con el constructor JList(DefaultListModel). A la inversa, podemos obtener el objeto DefaultListModel a partir de una lista JList mediante:

Ya sabemos lo suficiente para escribir la siguiente aplicación:

Los componentes de esta ventana son los siguientes:
n.º | tipo | nombre | función |
1 | JTextField | txtSaisie | campo de entrada |
2 | JList | jList1 | lista contenida en un contenedor jScrollPane1 |
3 | JList | jList2 | lista contenida en un contenedor jScrollPane2 |
4 | JButton | cmd1To2 | transfiere los elementos seleccionados de la lista 1 a la lista 2 |
5 | JButton | cmd2To1 | hace lo contrario |
6 | JButton | cmdRaz1 | vacía la lista 1 |
7 | JButton | cmdRaz2 | vacía la lista 2 |
El usuario escribe texto en el campo (1) y lo valida. A continuación, se produce el evento actionPerformed en el campo de entrada, que se utiliza para añadir el texto introducido a la lista 1. Este es el código necesario para esta primera función:
public class interfaceAppli extends JFrame {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
JLabel jLabel2 = new JLabel();
JLabel jLabel3 = new JLabel();
JTextField txtSaisie = new JTextField();
JButton cmd1To2 = new JButton();
JButton cmd2To1 = new JButton();
DefaultListModel v1=new DefaultListModel();
DefaultListModel v2=new DefaultListModel();
JList jList1 = new JList(v1);
JList jList2 = new JList(v2);
JScrollPane jScrollPane1 = new JScrollPane();
JScrollPane jScrollPane2 = new JScrollPane();
JButton cmdRaz1 = new JButton();
JButton cmdRaz2 = new JButton();
JLabel jLabel4 = new JLabel();
/**Crear el marco*/
public interfaceAppli() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}//interfaceAppli
/**Inicializar el componente*/
private void jbInit() throws Exception {
...
txtSaisie.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
txtSaisie_actionPerformed(e);
}
});
...
// Jlist1 se coloca en el contenedor jScrollPane1
jScrollPane1.getViewport().add(jList1, null);
// Jlist2 se coloca en el contenedor jScrollPane2
jScrollPane2.getViewport().add(jList2, null);
...
}
/**Sustituido, para que podamos salir cuando se cierre la ventana*/
protected void processWindowEvent(WindowEvent e) {
...
}
void txtSaisie_actionPerformed(ActionEvent e) {
// El texto introducido se ha validado
// se recupera sin los espacios iniciales y finales
String texte=txtSaisie.getText().trim();
// si está vacío, no lo queremos
if(texte.equals("")){
// mensaje de error
JOptionPane.showMessageDialog(this,"Vous devez taper un texte",
"Erreur",JOptionPane.WARNING_MESSAGE);
// fin
return;
}//si
// si no está vacío, se añade a los valores de la lista 1
v1.addElement(texte);
// y se vacía el campo de entrada
txtSaisie.setText("");
}/// txtSaisie_actionperformed
}//clase
El código para transferir los elementos seleccionados de una lista a otra es el siguiente:
void cmd1To2_actionPerformed(ActionEvent e) {
// transferencia de los elementos seleccionados de la lista 1 a la lista 2
transfert(jList1,jList2);
}//cmd1To2
void cmd2To1_actionPerformed(ActionEvent e) {
// transferencia de los elementos seleccionados en jList2 a jList1
transfert(jList2,jList1);
}//cmd2TO1
private void transfert(JList L1, JList L2){
// transferencia de los elementos seleccionados de la lista 1 a la lista 2
// se recupera la matriz de índices de los elementos seleccionados en L1
int[] indices=L1.getSelectedIndices();
// ¿Hay que hacer algo?
if (indices.length==0) return;
// se recuperan los valores de L1
DefaultListModel v1=(DefaultListModel)L1.getModel();
// y los de L2
DefaultListModel v2=(DefaultListModel)L2.getModel();
for(int i=indices.length-1;i>=0;i--){
// se añaden a L2 los valores seleccionados en L1
v2.addElement(v1.elementAt(indices[i]));
// los elementos de L1 copiados en L2 deben eliminarse de L1
v1.removeElementAt(indices[i]);
}//para
}//transferencia
El código asociado a los botones Raz es de lo más sencillo:
void cmdRaz1_actionPerformed(ActionEvent e) {
// vaciar la lista 1
v1.removeAllElements();
}//comando Raz1
void cmdRaz2_actionPerformed(ActionEvent e) {
// vaciar lista 2
v2.removeAllElements();
}///cmd Raz2
5.2.5.4. Casillas de selección JCheckBox, botones de opción JButtonRadio
Nos proponemos escribir la siguiente aplicación:

Los componentes de la ventana son los siguientes:
n.º | tipo | nombre | función |
1 | JButtonRadio | jButtonRadio1 jButtonRadio2 jButtonRadio3 | 3 botones de opción que forman parte del grupo buttonGroup1 |
2 | JCheckBox | jCheckBox1 jCheckBox2 jCheckBox3 | 3 casillas de selección |
3 | JList | jList1 | una lista dentro de un contenedor jScrollPane1 |
4 | ButtonGroup | buttonGroup1 | componente no visible: sirve para agrupar los tres botones de opción, de modo que, cuando uno de ellos se active, los demás se desactiven. |
Un grupo de botones de opción se puede crear de la siguiente manera:
- se colocan cada uno de los botones de opción sin preocuparse por agruparlos
- se coloca en el contenedor un componente Swing ButtonGroup. Este componente no es visible. Por lo tanto, no aparece en el diseñador de la ventana. Sin embargo, sí aparece en su estructura:

Arriba, en la rama Autre, se pueden ver los atributos no visuales de la ventana. Una vez creado un grupo de botones de opción, se puede asociar a él cada uno de los botones de opción. Para ello, se seleccionan las propiedades del botón de opción:

y, en la propiedad buttonGroup del botón de opción, se introduce el nombre del grupo en el que se desea incluir el botón de opción, en este caso buttonGroup1. Se repite esta operación para los tres botones de opción.
El método principal de los botones de radio y las casillas de selección es el método isSelected(), que indica si la casilla o el botón está marcado. El texto asociado al componente se puede obtener con getText() y establecer con setText(String unTexte). La casilla o el botón de opción se puede marcar con el método setSelected(boolean value).
Al hacer clic en un botón de radio o en una casilla de selección, se activa el evento actionPerformed. En el código siguiente, utilizamos este evento para realizar un seguimiento de los cambios en los valores de los botones de radio y las casillas de selección:
public class interfaceAppli extends JFrame {
JPanel contentPane;
JRadioButton jRadioButton1 = new JRadioButton();
JRadioButton jRadioButton2 = new JRadioButton();
JRadioButton jRadioButton3 = new JRadioButton();
JCheckBox jCheckBox1 = new JCheckBox();
JCheckBox jCheckBox2 = new JCheckBox();
JCheckBox jCheckBox3 = new JCheckBox();
ButtonGroup buttonGroup1 = new ButtonGroup();
JScrollPane jScrollPane1 = new JScrollPane();
DefaultListModel valeurs=new DefaultListModel();
JList jList1 = new JList(valeurs);
/**Crear el marco*/
public interfaceAppli() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar el componente*/
private void jbInit() throws Exception {
jRadioButton1.setSelected(true);
jRadioButton1.setText("un");
jRadioButton1.setBounds(new Rectangle(57, 31, 49, 23));
jRadioButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
afficheRadioButtons(e);
}
});
jRadioButton2.setBounds(new Rectangle(113, 30, 49, 23));
jRadioButton2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
afficheRadioButtons(e);
}
});
jRadioButton2.setText("deux");
jRadioButton3.setBounds(new Rectangle(168, 30, 49, 23));
jRadioButton3.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
afficheRadioButtons(e);
}
});
jRadioButton3.setText("trois");
// los botones de opción están agrupados
buttonGroup1.add(jRadioButton1);
buttonGroup1.add(jRadioButton2);
buttonGroup1.add(jRadioButton3);
// casillas de selección
jCheckBox1.setText("A");
jCheckBox1.setBounds(new Rectangle(58, 69, 32, 17));
jCheckBox1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
afficheCases(e);
}
});
jCheckBox2.setBounds(new Rectangle(112, 69, 40, 17));
jCheckBox2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
afficheCases(e);
}
});
jCheckBox2.setText("B");
jCheckBox3.setText("C");
jCheckBox3.setBounds(new Rectangle(170, 69, 37, 17));
jCheckBox3.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
afficheCases(e);
}
});
....
}
/**Sustituido, para que podamos salir cuando se cierre la ventana*/
protected void processWindowEvent(WindowEvent e) {
...
}
private void afficheRadioButtons(ActionEvent e){
// muestra los valores de los 3 botones de opción
valeurs.addElement("boutons radio=("+jRadioButton1.isSelected()+","+
jRadioButton2.isSelected()+","+jRadioButton3.isSelected()+")");
}//afficheRadioButtons
void afficheCases(ActionEvent e) {
// muestra los valores de las casillas de selección
valeurs.addElement("cases à cocher=["+jCheckBox1.isSelected()+","+
jCheckBox2.isSelected()+","+jCheckBox3.isSelected()+")");
}//afficheCases
}//clasifica
A continuación se muestra un ejemplo de ejecución:

5.2.5.5. componente JScrollBar
Creemos la siguiente aplicación:

n.º | tipo | nombre | función |
1 | JScrollBar | jScrollBar1 | un variador horizontal |
2 | JScrollBar | jScrollBar2 | un variador vertical |
3 | JTextField | txtvaleurHS | muestra el valor del variador horizontal 1; también permite fijar dicho valor |
4 | JTextField | txtvaleurVS | muestra el valor del regulador vertical 2; también permite fijar dicho valor |
- Un regulador JScrollBar permite al usuario seleccionar un valor dentro de un rango de valores enteros, representado por la «banda» del regulador sobre la que se desplaza un cursor.
- En un regulador horizontal, el extremo izquierdo representa el valor mínimo del rango, el extremo derecho el valor máximo y el cursor el valor actual seleccionado. En un regulador vertical, el mínimo está representado por el extremo superior y el máximo por el extremo inferior. El par (mín., máx.) tiene por defecto el valor (0,100).
- Al hacer clic en los extremos del regulador, el valor varía en un incremento (positivo o negativo) según el extremo en el que se haya hecho clic, denominado unitIncrement, cuyo valor por defecto es 1.
- Al hacer clic a ambos lados del cursor, el valor varía en un incremento (positivo o negativo) según el extremo en el que se haya hecho clic, denominado blockIncrement, cuyo valor por defecto es 10.
- Estos cinco valores (mín., máx., valor, unitIncrement, blockIncrement) pueden obtenerse mediante los métodos getMinimum(), getMaximum(), getValue(), getUnitIncrement() y getBlockIncrement(), todos los cuales devuelven un entero y pueden establecerse mediante los métodos setMinimum(int min), setMaximum(int max), setValue(int val), setUnitIncrement(int uInc), setBlockIncrement(int bInc)
Hay algunos aspectos que conviene conocer sobre el uso de los componentes JScrollBar. En primer lugar, se encuentra en la barra de componentes de Swing:

Al colocarlo en el contenedor, su orientación predeterminada es vertical. Se puede cambiar a horizontal mediante la propiedad orientation que se indica a continuación:

En la hoja de propiedades anterior se puede ver que tenemos acceso a las propiedades minimum, maximum, value, unitIncrement, blockIncrement y JScrollbar. Por lo tanto, se pueden establecer durante el diseño. Cuando se coloca una barra de desplazamiento en el contenedor, su «rango de variación» no aparece:

Este problema se puede solucionar añadiendo un borde al componente. Esto se hace mediante su propiedad border, que puede adoptar diferentes valores:

Este es, por ejemplo, el resultado de RaisedBevel:
![]()
Al hacer clic en el extremo superior de un control deslizante vertical, su valor disminuye. Esto puede sorprender al usuario medio, que normalmente espera que el valor «aumente». Este problema se soluciona asignando un valor negativo a unitIncrement y blockIncrement.
¿Cómo se puede seguir la evolución de un control deslizante? Cuando cambia su valor, se produce el evento adjustmentValueChanged. Basta con asociar un procedimiento a este evento para recibir una notificación cada vez que varíe el valor de la barra de desplazamiento.

El código útil de nuestra aplicación es el siguiente:
....
public class cadreAppli extends JFrame {
JPanel contentPane;
JScrollBar jScrollBar1 = new JScrollBar();
Border border1;
JTextField txtValeurHS = new JTextField();
JScrollBar jScrollBar2 = new JScrollBar();
JTextField txtValeurVS = new JTextField();
TitledBorder titledBorder1;
/**Crear el marco*/
public cadreAppli() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar el componente*/
private void jbInit() throws Exception {
...
// un borde para las barras de desplazamiento
border1 = BorderFactory.createBevelBorder(BevelBorder.RAISED,Color.white,Color.white,new Color(134, 134, 134),new Color(93, 93, 93));
// sin título en el borde
titledBorder1 = new TitledBorder("");
jScrollBar1.setOrientation(JScrollBar.HORIZONTAL);
jScrollBar1.setBorder(BorderFactory.createRaisedBevelBorder());
jScrollBar1.setAutoscrolls(true);
jScrollBar1.setBounds(new Rectangle(37, 17, 218, 20));
jScrollBar1.addAdjustmentListener(new java.awt.event.AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
jScrollBar1_adjustmentValueChanged(e);
}
});
txtValeurHS.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
txtValeurHS_actionPerformed(e);
}
});
jScrollBar2.setBounds(new Rectangle(39, 51, 30, 27));
jScrollBar2.addAdjustmentListener(new java.awt.event.AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
jScrollBar2_adjustmentValueChanged(e);
}
});
jScrollBar2.setAutoscrolls(true);
jScrollBar2.setUnitIncrement(-1);
jScrollBar2.setBorder(BorderFactory.createRaisedBevelBorder());
txtValeurVS.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
txtValeurVS_actionPerformed(e);
}
});
......
}
/**Sustituido, para que podamos salir cuando se cierre la ventana*/
protected void processWindowEvent(WindowEvent e) {
...
}
void jScrollBar1_adjustmentValueChanged(AdjustmentEvent e) {
// el valor de la barra de desplazamiento 1 ha cambiado
txtValeurHS.setText(""+jScrollBar1.getValue());
}
void jScrollBar2_adjustmentValueChanged(AdjustmentEvent e) {
// el valor de la barra de desplazamiento 2 ha cambiado
txtValeurVS.setText(""+jScrollBar2.getValue());
}
void txtValeurHS_actionPerformed(ActionEvent e) {
// se fija el valor de la barra de desplazamiento horizontal
setValeur(jScrollBar1,txtValeurHS);
}
void txtValeurVS_actionPerformed(ActionEvent e) {
// se fija el valor de la barra de desplazamiento vertical
setValeur(jScrollBar2,txtValeurVS);
}
private void setValeur(JScrollBar jS, JTextField jT){
// se fija el valor de la barra de desplazamiento jS con el texto del campo jT
int valeur=0;
try{
valeur=Integer.parseInt(jT.getText());
jS.setValue(valeur);
}
catch (Exception e){
// se muestra el error
afficher(""+e);
}//try-catch
}//setValeur
void afficher(String message){
// muestra un mensaje en un cuadro
JOptionPane.showMessageDialog(this,message,"Menus",JOptionPane.INFORMATION_MESSAGE);
}//mostrar
}
A continuación se muestra un ejemplo de ejecución:

5.2.5.6. Componente JTextArea
El componente JTextArea es un componente en el que se pueden introducir varias líneas de texto, a diferencia del componente JTextField, en el que solo se puede introducir una línea. Si este componente se coloca en un contenedor desplazable (JScrollPane), se obtiene un campo de entrada de texto desplazable. Este tipo de componente podría encontrarse, por ejemplo, en una aplicación de correo electrónico en la que el texto del mensaje que se va a enviar se escribiría en un componente JTextArea. Los métodos habituales son String getText() para conocer el contenido del campo de texto, setText(String unTexte) para introducir unTexte en el campo de texto, y append(String unTexte) para añadir unTexte al texto ya presente en el campo de texto. Consideremos la siguiente aplicación:

n.º | tipo | nombre | función |
1 | JTextArea | txtTexte | un campo de texto multilínea |
2 | JButton | cmdAfficher | muestra el contenido de 1 en un cuadro de diálogo |
3 | JButton | cmdEffacer | borra el contenido de 1 |
4 | JTextField | txtAjout | texto añadido al texto de 1 al pulsar la tecla Intro. |
5 | JScrollPane | jScrollPane1 | Contenedor con desplazamiento en el que se ha colocado el cuadro de texto 1 para que sea un cuadro de texto con desplazamiento. |
El código correspondiente es el siguiente:
.....
public class cadreAppli extends JFrame {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
JButton cmdAfficher = new JButton();
JScrollPane jScrollPane1 = new JScrollPane();
JTextArea txtTexte = new JTextArea();
JLabel jLabel2 = new JLabel();
JTextField txtAjout = new JTextField();
JButton cmdEffacer = new JButton();
/**Crear el marco*/
public cadreAppli() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar el componente*/
private void jbInit() throws Exception {
cmdAfficher.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdAfficher_actionPerformed(e);
}
});
txtAjout.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
txtAjout_actionPerformed(e);
}
});
cmdEffacer.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdEffacer_actionPerformed(e);
}
});
.......
jScrollPane1.getViewport().add(txtTexte, null);
}
/**Sustituido, para que podamos salir cuando se cierre la ventana*/
protected void processWindowEvent(WindowEvent e) {
........
}
void cmdAfficher_actionPerformed(ActionEvent e) {
// muestra el contenido de TextArea
afficher(txtTexte.getText());
}
void afficher(String message){
// muestra un mensaje en un cuadro
JOptionPane.showMessageDialog(this,message,"Suivi",JOptionPane.INFORMATION_MESSAGE);
}// mostrar
void cmdEffacer_actionPerformed(ActionEvent e) {
txtTexte.setText("");
}//cmdEffacer_actionPerformed
void txtAjout_actionPerformed(ActionEvent e) {
// añadir texto
txtTexte.append(txtAjout.getText());
// borrar y añadir
txtAjout.setText("");
}//
}
5.2.6. Eventos del ratón
Cuando se dibuja en un contenedor, es importante conocer la posición del ratón para, por ejemplo, mostrar un punto al hacer clic. Los movimientos del ratón provocan eventos en el contenedor por el que se desplaza. A continuación se muestran, por ejemplo, los que ofrece JBuilder para un contenedor JPanel:

mouseClicked | clic del ratón |
mouseDragged | el ratón se desplaza, botón izquierdo pulsado |
mouseEntered | el ratón acaba de entrar en el área del contenedor |
mouseExited | el ratón acaba de salir de la superficie del contenedor |
mouseMoved | el ratón se mueve |
mousePressed | Se pulsa el botón izquierdo del ratón |
mouseReleased | Se suelta el botón izquierdo del ratón |
Aquí tienes un programa que te ayudará a comprender mejor en qué momentos se producen los distintos eventos del ratón:

n.º | tipo | nombre | función |
1 | JTextField | txtPosition | para mostrar la posición del ratón en el contenedor (si procede, MouseMoved) |
2 | JList | lstAffichage | para mostrar los eventos del ratón distintos de MouseMoved |
3 | JButton | cmdEffacer | para borrar el contenido de 2 |
Al ejecutar este programa, esto es lo que se obtiene al hacer clic:

Los eventos se apilan de arriba abajo en la lista. Por lo tanto, la captura de pantalla anterior indica que un clic provoca tres eventos, en este orden:
- MousePressed al pulsar el botón
- MouseReleased al soltarlo
- MouseClicked, que indica que la sucesión de los dos eventos anteriores se considera un clic. Podría tratarse de un doble clic. Pero, en el ejemplo anterior, la información clickCount=1 indica que se trata de un clic simple.
Ahora, si pulsamos el botón, movemos el ratón y soltamos el botón:

Aquí vemos los tres eventos:
- MousePressed al pulsar inicialmente el botón
- MouseDragged al mover el ratón con el botón pulsado
- MouseReleased al soltar el botón
En los dos ejemplos anteriores, se observa que un evento del ratón trae consigo diversa información, entre la que se incluyen las coordenadas (x, y) del ratón, por ejemplo (408,65) en la primera línea anterior.
Si seguimos así, descubrimos que el evento MouseExited se activa en cuanto el ratón sale del contenedor o pasa por encima de uno de sus componentes. En este último caso, el contenedor recibe el evento MouseExited y el componente, el evento MouseEntered. Ocurrirá lo contrario cuando el ratón salga del componente para volver al contenedor.
¿Qué ocurre al hacer doble clic?

Se producen exactamente los mismos eventos que con un clic simple. La única diferencia es que el evento incluye la información clickCount=2 (véase más arriba), lo que indica que, de hecho, se ha producido un doble clic.
El código relevante de esta aplicación es el siguiente:
public class Cadre1 extends JFrame {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
JTextField txtPosition = new JTextField();
JScrollPane jScrollPane1 = new JScrollPane();
DefaultListModel valeurs=new DefaultListModel();
JList lstAffichage = new JList(valeurs);
JButton cmdEffacer = new JButton();
/**Crear el marco*/
public Cadre1() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar el componente*/
private void jbInit() throws Exception {
contentPane.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
contentPane_mouseMoved(e);
}
public void mouseDragged(MouseEvent e) {
contentPane_mouseDragged(e);
}
});
contentPane.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseEntered(MouseEvent e) {
contentPane_mouseEntered(e);
}
public void mouseExited(MouseEvent e) {
contentPane_mouseExited(e);
}
public void mousePressed(MouseEvent e) {
contentPane_mousePressed(e);
}
public void mouseClicked(MouseEvent e) {
contentPane_mouseClicked(e);
}
public void mouseReleased(MouseEvent e) {
contentPane_mouseReleased(e);
}
});
cmdEffacer.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdEffacer_actionPerformed(e);
}
});
jScrollPane1.getViewport().add(lstAffichage, null);
...............
}
/**Sustituido, para que podamos salir cuando se cierre la ventana*/
protected void processWindowEvent(WindowEvent e) {
.........
}
void contentPane_mouseMoved(MouseEvent e) {
txtPosition.setText("("+e.getX()+","+e.getY()+")");
}
void contentPane_mouseDragged(MouseEvent e) {
afficher(e);
}
void contentPane_mouseEntered(MouseEvent e) {
afficher(e);
}
void afficher(MouseEvent e){
// muestra el evento e en la lista lstAffichage
valeurs.insertElementAt(e,0);
}
void contentPane_mouseExited(MouseEvent e) {
afficher(e);
}
void contentPane_mousePressed(MouseEvent e) {
afficher(e);
}
void contentPane_mouseClicked(MouseEvent e) {
afficher(e);
}
void contentPane_mouseReleased(MouseEvent e) {
afficher(e);
}
void cmdEffacer_actionPerformed(ActionEvent e) {
// borra la lista
valeurs.removeAllElements();
}
}
5.2.7. Crear una ventana con menú
Veamos ahora cómo crear una ventana con menú con JBuilder. Vamos a crear la siguiente ventana:


Crea un nuevo proyecto que, inicialmente, contenga una ventana vacía. Selecciona en la lista de componentes «Contenedores Swing» el componente JMenuBar (véase la figura 1 más abajo) y arrástralo hasta la ventana que estás diseñando.

No aparece nada en la ventana de diseño, pero el componente JMenuBar aparece en el panel de estructura de la ventana:

Haz doble clic en el elemento jMenuBar1 anterior para acceder al menú en modo de diseño:

1 | Insertar un elemento de menú |
2 | insertar un separador |
3 | Insertar un menú anidado |
4 | Eliminar un elemento del menú |
5 | Desactivar un elemento del menú |
6 | Elemento de menú con casilla de selección |
7 | Invertir el botón de opción |
Para crear tu primer elemento de menú, escribe «Opciones A» en la casilla A de arriba y, a continuación, debajo, en este orden: A1, A2, separador, A3, A4.

A continuación, al lado:

Utiliza la herramienta 3 para indicar que B3 es un submenú anidado.
A medida que se va diseñando el menú, la estructura lógica de nuestra ventana va evolucionando:

Si ejecutamos ahora nuestra aplicación, veremos una ventana vacía sin menú. Tenemos que asociar el menú creado a nuestra ventana. Para ello, en la estructura de la ventana, selecciona el objeto this:

A continuación, tendrá acceso a las propiedades de this:

Una de ellas es JMenuBar, que sirve para establecer el menú que se asociará a la ventana. Haga clic en la celda situada a la derecha de JMenuBar. A continuación, se le mostrarán todos los menús creados. En este caso, solo tendremos jMenuBar1. Selecciónalo.
Ejecute la aplicación (F9):

Ahora tenemos un menú, pero las opciones, por el momento, no hacen nada. Las opciones del menú se tratan como componentes: tienen propiedades y eventos. En la estructura del menú, selecciona la opción jMenuItem1:

De este modo, tendrá acceso a sus propiedades y eventos:

Seleccione la página de eventos y haga clic en la celda situada a la derecha del evento actionPerformed: este es el evento que se produce al hacer clic en un elemento del menú. Se le propone un procedimiento de tratamiento por defecto. Haga doble clic en él para acceder a su código:

Escribiremos el siguiente código sencillo:
void jMenuItem1_actionPerformed(ActionEvent e) {
afficher("L'option A1 a été sélectionnée");
}
void afficher(String message){
// muestra un mensaje en un cuadro de diálogo
JOptionPane.showMessageDialog(this,message,"Menus",JOptionPane.INFORMATION_MESSAGE);
}//mostrar
Ejecuta la aplicación y selecciona la opción A1 para obtener el siguiente mensaje:

El código útil de esta aplicación es el siguiente:
.....
public class Cadre1 extends JFrame {
JPanel contentPane;
BorderLayout borderLayout1 = new BorderLayout();
JMenuBar jMenuBar1 = new JMenuBar();
JMenu jMenu1 = new JMenu();
JMenuItem jMenuItem1 = new JMenuItem();
JMenuItem jMenuItem2 = new JMenuItem();
JMenuItem jMenuItem3 = new JMenuItem();
JMenuItem jMenuItem4 = new JMenuItem();
JMenu jMenu2 = new JMenu();
JMenuItem jMenuItem5 = new JMenuItem();
JMenuItem jMenuItem6 = new JMenuItem();
JMenu jMenu3 = new JMenu();
JMenuItem jMenuItem7 = new JMenuItem();
JMenuItem jMenuItem8 = new JMenuItem();
JMenuItem jMenuItem9 = new JMenuItem();
/**Crear el marco*/
public Cadre1() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar el componente*/
private void jbInit() throws Exception {
// la ventana está asociada a un menú
this.setJMenuBar(jMenuBar1);
jMenu1.setText("Options A");
jMenuItem1.setText("A1");
jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
jMenuItem1_actionPerformed(e);
}
});
jMenuItem2.setText("A2");
jMenuItem3.setText("A3");
jMenuItem4.setText("A4");
jMenu2.setText("Options B");
jMenuItem5.setText("B1");
jMenuItem6.setText("B2");
jMenu3.setText("B3");
jMenuItem7.setText("B31");
jMenuItem8.setText("B32");
jMenuItem9.setText("B4");
jMenuBar1.add(jMenu1);
jMenuBar1.add(jMenu2);
jMenu1.add(jMenuItem1);
jMenu1.add(jMenuItem2);
jMenu1.addSeparator();
jMenu1.add(jMenuItem3);
jMenu1.add(jMenuItem4);
jMenu2.add(jMenuItem5);
jMenu2.add(jMenuItem6);
jMenu2.add(jMenu3);
jMenu2.add(jMenuItem9);
jMenu3.add(jMenuItem7);
jMenu3.add(jMenuItem8);
}
/**Sustituido, para que podamos salir cuando se cierre la ventana*/
protected void processWindowEvent(WindowEvent e) {
....
}
void jMenuItem1_actionPerformed(ActionEvent e) {
afficher("L'option A1 a été sélectionnée");
}
void afficher(String message){
// muestra un mensaje en un cuadro de diálogo
JOptionPane.showMessageDialog(this,message,"Menus",JOptionPane.INFORMATION_MESSAGE);
}//Mostrar
}
5.3. Cuadros de diálogo
5.3.1. Cuadros de mensaje
Ya hemos utilizado la clase JOptionPane para mostrar mensajes. Así, el siguiente código:
import javax.swing.*;
public class dialog1 {
public static void main(String arg[]){
JOptionPane.showMessageDialog(null,"Un message","Titre de la boîte",JOptionPane.INFORMATION_MESSAGE);
}
}
muestra el siguiente cuadro:

Al cerrar esta ventana, esta desaparece, pero el hilo de ejecución en el que se ejecutaba no se detiene. Este fenómeno no suele producirse. Los cuadros de diálogo se utilizan dentro de una aplicación que, en algún momento, utiliza una instrucción System.exit(n) para detener todos los hilos. Lo tendremos en cuenta en los ejemplos siguientes, todos ellos basados en el mismo modelo. En DOS, la aplicación se puede interrumpir con Ctrl-C. Con JBuilder, se utilizará la opción Ejecutar/Reiniciar el programa (Ctrl-F2). Por otra parte, el primer argumento de showMessageDialog es aquí null. Por lo general, no es así. Suele ser this, donde this designa la ventana principal de la aplicación.
5.3.2. Aspecto y comportamiento
El aspecto del cuadro anterior podría ser diferente. Es posible configurar este aspecto mediante la clase javax.swing.UIManager. Cuando comentamos el código generado por JBuilder para nuestra primera ventana, nos encontramos con una instrucción en la que no nos detuvimos:
El método setLookAndFeel de la clase UIManager (UI = Interfaz de usuario) permite definir el aspecto de las interfaces gráficas. La clase UIManager dispone de un método que permite conocer las «apariencias» posibles para las interfaces:
static UIManager.LookAndFeelInfo[] | getInstalledLookAndFeels() |
El método devuelve una matriz de elementos de tipo LookAndFeelInfo. Esta clase tiene un método:
String | getClassName() |
que devuelve el nombre de la clase que «implementa» un aspecto determinado. Probemos el siguiente programa:
import javax.swing.*;
public class LookAndFeels {
// muestra los «look and feels» disponibles
public static void main(String[] args) {
// lista los «look and feels» instalados
UIManager.LookAndFeelInfo[] lf=UIManager.getInstalledLookAndFeels();
// visualización
for(int i=0;i<lf.length;i++){
System.out.println(lf[i].getClassName());
}//para
}//principal
}//clasifica
Da los siguientes resultados:
javax.swing.plaf.metal.MetalLookAndFeel
com.sun.java.swing.plaf.motif.MotifLookAndFeel
com.sun.java.swing.plaf.windows.WindowsLookAndFeel
Por lo tanto, parece que hay tres «aspectos» diferentes. Volvamos a nuestro programa de visualización de mensajes probando los diferentes aspectos posibles:
import javax.swing.*;
public class LookAndFeel2 {
// muestra los «look and feels» disponibles
public static void main(String[] args) {
// lista de los «look and feels» instalados
UIManager.LookAndFeelInfo[] lf=UIManager.getInstalledLookAndFeels();
// visualización
for(int i=0;i<lf.length;i++){
// gestor de apariencia
try{
UIManager.setLookAndFeel(lf[i].getClassName());
}catch(Exception ex){
System.err.println(ex.getMessage());
}//captura
// mensaje
JOptionPane.showMessageDialog(null,"Un message",lf[i].getClassName(),JOptionPane.INFORMATION_MESSAGE);
}//for
}//main
}//clase
Al ejecutarlo, se obtienen los siguientes resultados:
![]() | ![]() | ![]() |
que corresponden, de derecha a izquierda, a los «estilos» Metal, Motivo y Windows.
5.3.3. Cuadros de confirmación
La clase JOptionPane dispone de un método showConfirmDialog para mostrar cuadros de confirmación con los botones Oui, Non y Annuler. Hay varios métodos showConfirmDialog sobrescritos. Analizamos uno de ellos:
static int | showConfirmDialog(Component parentComponent, Object message, String title, int optionType) |
parentComponent | el componente padre del cuadro de diálogo. A menudo es la ventana o el valor null |
message | el mensaje que se va a mostrar |
title | el título del cuadro de diálogo |
optionType | JOptionPane.YES_NO_OPTION: botones «Sí», «No» JOptionPane.YES_NO_CANCEL_OPTION: botones «Sí», «No», «Cancelar» |
El resultado devuelto por el método es:
JOptionPane.YES_OPTION | el usuario ha hecho clic en «Sí» |
JOptionPane.NO_OPTION | El usuario ha hecho clic en «No» |
JOptionPane.CANCEL_OPTION | El usuario ha hecho clic en «Cancelar» |
JOptionPane.CLOSED_OPTION | El usuario ha cerrado el cuadro de diálogo |
He aquí un ejemplo:
import javax.swing.*;
public class confirm1 {
public static void main(String[] args) {
// muestra cuadros de confirmación
int réponse;
affiche(JOptionPane.showConfirmDialog(null,"Voulez-vous continuer ?","Confirmation",JOptionPane.YES_NO_OPTION));
affiche(JOptionPane.showConfirmDialog(null,"Voulez-vous continuer ?","Confirmation",JOptionPane.YES_NO_CANCEL_OPTION));
}//principal
private static void affiche(int réponse){
// indica qué tipo de respuesta se ha recibido
switch(réponse){
case JOptionPane.YES_OPTION :
System.out.println("Oui");
break;
case JOptionPane.NO_OPTION :
System.out.println("Non");
break;
case JOptionPane.CANCEL_OPTION :
System.out.println("Annuler");
break;
case JOptionPane.CLOSED_OPTION :
System.out.println("Fermeture");
break;
}//interruptor
}//pantalla
}//clasificar
![]() | ![]() |
En la consola aparecen los mensajes Non y Annuler.
5.3.4. Campo de entrada
La clase JOptionPane también ofrece la posibilidad de realizar una entrada mediante el método showInputDialog. Una vez más, existen varios métodos sobrecargados. A continuación, presentamos uno de ellos:
static String | showInputDialog(Component parentComponent, Object message, String title, int messageType) |
Los argumentos son los mismos que ya hemos visto en varias ocasiones. El método devuelve la cadena de caracteres introducida por el usuario. A continuación se muestra un ejemplo:
import javax.swing.*;
public class input1 {
public static void main(String[] args) {
// introducción
System.out.println("Chaîne saisie ["+
JOptionPane.showInputDialog(null,"Quel est votre nom","Saisie du nom",JOptionPane.QUESTION_MESSAGE )
+ "]");
}//mano
}//clase
La visualización del cuadro de entrada:

Visualización de la consola:
5.4. Cuadros de selección
Ahora nos centraremos en varios cuadros de selección predefinidos en Java 2:
JFileChooser | cuadro de selección que permite seleccionar un archivo en el árbol de archivos |
JColorChooser | cuadro de selección que permite elegir un color |
5.4.1. Cuadro de selección JFileChooser
Vamos a crear la siguiente aplicación:

Los controles son los siguientes:
N.º | tipo | nombre | función |
0 | JScrollPane | jScrollPane1 | Contenedor deslizante para el cuadro de texto 1 |
1 | JTextArea, que a su vez se encuentra dentro de JScrollPane | txtTexte | Texto escrito por el usuario o cargado desde un archivo |
2 | JButton | btnSauvegarder | permite guardar el texto de 1 en un archivo de texto |
3 | JButton | btnCharger | permite cargar el contenido de un archivo de texto en 1 |
4 | JButton | btnEffacer | borra el contenido de 1 |
Se utiliza un control no visual: jFileChooser1. Este se toma de la paleta de contenedores Swing de JBuilder:

Colocamos el componente en la ventana de diseño, pero fuera del formulario. Aparece en la lista de componentes:

A continuación, mostramos el código relevante del programa para tener una visión general:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.io.*;
public class dialogues extends JFrame {
// los componentes del marco
JPanel contentPane;
JButton btnSauvegarder = new JButton();
JButton btnCharger = new JButton();
JButton btnEffacer = new JButton();
JScrollPane jScrollPane1 = new JScrollPane();
JTextArea txtTexte = new JTextArea();
JFileChooser jFileChooser1 = new JFileChooser();
// los filtros de archivos
javax.swing.filechooser.FileFilter filtreTxt = null;
//Crear el marco
public dialogues() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
// otras inicializaciones
moreInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
// moreInit
private void moreInit(){
// inicializaciones al crear la ventana
// filtro *.txt
filtreTxt = new javax.swing.filechooser.FileFilter(){
public boolean accept(File f){
// ¿Se acepta «f»?
return f.getName().toLowerCase().endsWith(".txt");
}//aceptar
public String getDescription(){
// descripción del filtro
return "Fichiers Texte (*.txt)";
}//getDescription
};
// se añade el filtro
jFileChooser1.addChoosableFileFilter(filtreTxt);
// también queremos el filtro de todos los archivos
jFileChooser1.setAcceptAllFileFilterUsed(true);
// se establece el directorio de origen de la caja FileChooser en el directorio actual
jFileChooser1.setCurrentDirectory(new File("."));
}
//Inicializar el componente
private void jbInit() throws Exception {
.......................
}
//Sustituido, así podemos salir cuando se cierre la ventana
protected void processWindowEvent(WindowEvent e) {
......................
}
}
void btnCharger_actionPerformed(ActionEvent e) {
// Selección de un archivo mediante un objeto JFileChooser
// Se establece el filtro inicial
jFileChooser1.setFileFilter(filtreTxt);
// se muestra el cuadro de selección
int returnVal = jFileChooser1.showOpenDialog(this);
// ¿Ha seleccionado algo el usuario?
if(returnVal == JFileChooser.APPROVE_OPTION) {
// se introduce el archivo en el campo de texto
lireFichier(jFileChooser1.getSelectedFile());
}//si
}//btnCharger_actionPerformed
// lireFichier
private void lireFichier(File fichier){
// muestra el contenido del archivo de texto «fichier» en el campo de texto
// se borra el campo de texto
txtTexte.setText("");
// algunos datos
BufferedReader IN=null;
String ligne=null;
try{
// apertura del archivo en modo de lectura
IN=new BufferedReader(new FileReader(fichier));
// se lee el archivo línea por línea
while((ligne=IN.readLine())!=null){
txtTexte.append(ligne+"\n");
}//while
// cierre del archivo
IN.close();
}catch(Exception ex){
// se ha producido un error
txtTexte.setText(""+ex);
}//catch
}
// borrar
void btnEffacer_actionPerformed(ActionEvent e) {
// se borra el cuadro de texto
txtTexte.setText("");
}
// guardar
void btnSauvegarder_actionPerformed(ActionEvent e) {
// guarda el contenido del cuadro de texto en un archivo
// se establece el filtro inicial
jFileChooser1.setFileFilter(filtreTxt);
// se muestra el cuadro de selección de guardado
int returnVal = jFileChooser1.showSaveDialog(this);
// ¿Ha seleccionado algo el usuario?
if(returnVal == JFileChooser.APPROVE_OPTION) {
// se escribe el contenido del cuadro de texto en un archivo
écrireFichier(jFileChooser1.getSelectedFile());
}//si
}
// lireFichier
private void écrireFichier(File fichier){
// escribe el contenido del cuadro de texto en un archivo
// algunos datos
PrintWriter PRN=null;
try{
// abre el archivo en modo de escritura
PRN=new PrintWriter(new FileWriter(fichier));
// se escribe el contenido del cuadro de texto
PRN.print(txtTexte.getText());
// cierre del archivo
PRN.close();
}catch(Exception ex){
// se ha producido un error
txtTexte.setText(""+ex);
}//captura
}
No comentaremos el código de los métodos btnEffacer_Click, lireFichier y écrireFichier, ya que no aportan nada que no hayamos visto ya. Nos centraremos en la clase JFileChooser y su uso. Esta clase es compleja, del tipo «complicadísima». Aquí solo utilizamos los siguientes métodos:
addChoosableFilter(FileFilter) | establece los tipos de archivo que se ofrecen para la selección |
setAcceptAllFileFilterUsed(boolean) | indica si el tipo «Todos los archivos» debe ofrecerse para la selección o no |
File getSelectedFile() | el archivo (File) seleccionado por el usuario |
int showSaveDialog() | método que muestra el cuadro de diálogo de selección de guardado. Devuelve un resultado de tipo int. El valor jFileChooser.APPROVE_OPTION indica que el usuario ha realizado una selección válida. De lo contrario, o bien ha cancelado la selección, o bien se ha producido un error. |
setCurrentDirectory | para establecer el directorio inicial desde el que el usuario comenzará a explorar el sistema de archivos |
setFileFilter(FileFilter) | para establecer el filtro activo |
El método showSaveDialog muestra un cuadro de selección similar al siguiente:

1 | lista desplegable creada con el método addChoosableFilter. Contiene lo que se denomina filtros de selección, representados por la clase FileFilter. Es el desarrollador quien debe definir estos filtros y añadirlos a la lista 1. |
2 | carpeta actual, establecida mediante el método setCurrentDirectory si se ha utilizado dicho método; de lo contrario, la carpeta actual será la carpeta «Mis documentos» en Windows o el directorio de inicio en Unix. |
3 | nombre del archivo seleccionado o introducido directamente por el usuario. Estará disponible con el método getSelectedFile() |
4 | Botones «Guardar»/«Cancelar». Si se utiliza el botón Enregistrer, el método showSaveDialog devuelve el resultado jFileChooser.APPROVE_OPTION |
¿Cómo se crean los filtros de archivos de la lista desplegable 1? Los filtros se añaden a la lista 1 mediante el método:
addChoosableFilter(FileFilter) | establece los tipos de archivo que se ofrecen para la selección |
de la clase JFileChooser. Nos queda por conocer la clase FileFilter. En realidad, se trata de la clase javax.swing.filechooser.FileFilter, que es una clase abstracta, c.a.d, una clase que no puede instanciarse, sino solo derivarse. Se define de la siguiente manera:
FileFilter() | constructor |
boolean accept(File) | indica si el archivo f pertenece al filtro o no |
String getDescription() | cadena de descripción del filtro |
Veamos un ejemplo. Queremos que el menú desplegable 1 ofrezca un filtro para seleccionar los archivos *.txt con la descripción «Archivos de texto (*.txt)».
- Tenemos que crear una clase derivada de la clase FileFilter
- utilizar el método boolean accept(File f) para devolver el valor true si el nombre del archivo f termina en .txt
- utilizar el método String getDescription() para devolver la descripción «Archivos de texto (*.txt)»
Este filtro se podría definir en nuestra aplicación de la siguiente manera:
javax.swing.filechooser.FileFilter filtreTxt = new javax.swing.filechooser.FileFilter(){
public boolean accept(File f){
// ¿Se acepta «f»?
return f.getName().toLowerCase().endsWith(".txt");
}//aceptado
public String getDescription(){
// descripción del filtro
return "Fichiers Texte (*.txt)";
}//getDescription
};
Este filtro se añadiría a la lista de filtros del objeto jFileChooser1 mediante la instrucción:
Todo esto, junto con algunas otras inicializaciones, se lleva a cabo en el método moreInit, que se ejecuta al crear la ventana (véase el programa completo más arriba). El código del botón Sauvegarder es el siguiente:
void btnSauvegarder_actionPerformed(ActionEvent e) {
// guarda el contenido del cuadro de texto en un archivo
// se establece el filtro inicial
jFileChooser1.setFileFilter(filtreTxt);
// se muestra el cuadro de selección de guardado
int returnVal = jFileChooser1.showSaveDialog(this);
// ¿Ha seleccionado algo el usuario?
if(returnVal == JFileChooser.APPROVE_OPTION) {
// se escribe el contenido del cuadro de texto en un archivo
écrireFichier(jFileChooser1.getSelectedFile());
}//si
}
La secuencia de operaciones es la siguiente:
- se establece el filtro activo en *.txt para permitir al usuario buscar preferentemente este tipo de archivos. También está presente el filtro «Todos los archivos». Se ha añadido en el procedimiento moreInit. Por lo tanto, hay dos filtros.
- Se muestra el cuadro de selección de guardado. Aquí perdemos el control, ya que el usuario utiliza el cuadro de selección para indicar un archivo del sistema de archivos.
- Al salir del cuadro de selección, se comprueba el valor de retorno para ver si hay que guardar o no el cuadro de texto. En caso afirmativo, debe guardarse en el archivo obtenido mediante el método getSelectedFile.
El código relacionado con el botón «Cargar» es muy similar al del botón «Guardar».
void btnCharger_actionPerformed(ActionEvent e) {
// selección de un archivo mediante un objeto JFileChooser
// se establece el filtro inicial
jFileChooser1.setFileFilter(filtreTxt);
// se muestra el cuadro de selección
int returnVal = jFileChooser1.showOpenDialog(this);
// ¿Ha seleccionado algo el usuario?
if(returnVal == JFileChooser.APPROVE_OPTION) {
// se introduce el archivo en el campo de texto
lireFichier(jFileChooser1.getSelectedFile());
}//si
}//btnCharger_actionPerformed
Hay dos diferencias:
- para mostrar el cuadro de selección de archivos, se utiliza el método showOpenDialog en lugar del método showSaveDialog. El cuadro de selección que se muestra es similar al que muestra el método showSaveDialog.
- Si el usuario ha seleccionado correctamente un archivo, se llama al método lireFichier en lugar del método écrireFichier.
5.4.1.1. Cuadros de selección JColorChooser y JFontChooser
Continuamos con el ejemplo anterior añadiendo dos nuevos botones:

N.º | tipo | nombre | función |
6 | JButton | btnCouleur | para establecer el color de los caracteres de TextBox |
7 | JButton | btnPolice | para establecer la fuente de TextBox |
El componente JColorChooser, que permite mostrar un cuadro de selección de color, se encuentra en la lista de componentes Swing de JBuilder:

Colocamos este componente en la ventana de diseño, pero fuera del formulario. No es visible en el formulario, pero sí aparece en la lista de componentes de la ventana:

La clase JColorChooser es muy sencilla. Mostramos el cuadro de selección de colores con el método int showDialog:
static Color | showDialog(Component component, String title, Color initialColor) |
Component component | el componente padre del cuadro de selección, normalmente una ventana JFrame |
String title | el título que aparece en la barra de título del cuadro de selección |
Color intialColor | color seleccionado inicialmente en el cuadro de selección |
Si el usuario elige un color, el método devuelve un color; en caso contrario, devuelve el valor null. El código asociado al botón Couleur es el siguiente:
void btnCouleur_actionPerformed(ActionEvent e) {
// selección de un color de texto mediante el componente JColorChooser
Color couleur;
if((couleur=jColorChooser1.showDialog(this,"Choix d'une couleur",Color.BLACK))!=null){
// se establece el color de los caracteres del cuadro de texto
txtTexte.setForeground(couleur);
}//if
}
La clase Color se define en java.awt.Color. En ella se definen varias constantes, entre ellas Color.BLACK para el color negro. El cuadro de selección que se muestra es el siguiente

Curiosamente, la biblioteca Swing no ofrece ninguna clase para seleccionar un tipo de letra. Afortunadamente, existen recursos Java en Internet. Al realizar una búsqueda con la palabra clave «JFontChooser», que parece un nombre posible para una clase de este tipo, se encuentran varios resultados. El ejemplo que viene a continuación nos dará la oportunidad de configurar JBuilder para que utilice paquetes no previstos en su configuración inicial.
El paquete recuperado se llama swingextras.jar y se ha colocado en la carpeta <jdk>\jre\lib\perso, donde <jdk> designa el directorio de instalación del JDK utilizado por JBuilder. Podría haberse colocado en cualquier otro lugar.
![]() | ![]() |
Veamos el contenido del paquete SwingExtras.jar:

En él se encuentra el código fuente Java de los componentes que incluye el paquete. También se encuentran las propias clases:

De este archivo, cabe destacar que la clase JFontChooser se llama en realidad com.lamatek.swingextras.JFontChooser. Si no queremos escribir el nombre completo, tendremos que escribir al principio del programa:
¿Cómo encontrarán el compilador y la máquina virtual de Java este nuevo paquete? En el caso del uso directo de JDK, esto ya se ha explicado y el lector podrá consultar las explicaciones en el apartado sobre los paquetes de Java. A continuación detallamos el método que hay que utilizar con JBuilder. Los paquetes se configuran en el menú Opciones/Configurar los JDK:

1 | El botón Modifier (1) permite indicar a JBuilder qué JDK se va a utilizar. En este ejemplo, JBuilder había traído consigo el JDK 1.3.1. Cuando se lanzó el JDK 1.4, se instaló por separado del JBuilder y se utilizó el botón Modifier para indicar al JBuilder queutilizara a partir de entonces el JDK 1.4, indicando el directorio de instalación de este último |
2 | directorio raíz de JDK, que actualmente utiliza JBuilder |
3 | lista de archivos Java (.jar) utilizados por JBuilder. Se pueden añadir otros mediante el botón Ajouter (4) |
4 | El botón Ajouter (4) permite añadir nuevos paquetes que JBuilder utilizará tanto para la compilación como para la ejecución de los programas. Aquí lo hemos utilizado para añadir el paquete SwingExtras.jar (5) |
Ahora JBuilder está correctamente configurado para poder utilizar la clase JFontChooser. Sin embargo, necesitaríamos tener acceso a la definición de esta clase para utilizarla correctamente. El archivo swingextras.jar contiene archivos HTML que podríamos extraer para aprovecharlos. No es necesario. Se puede acceder directamente a la documentación de Java incluida en los archivos .jar desde JBuilder. Para ello, hay que configurar la pestaña Documentation (6) que aparece más arriba. Aparecerá la siguiente ventana:

El botón Ajouter nos permite indicar que el archivo SwingExtras.jar debe explorarse en busca de documentación. Una vez validado este paso, podemos comprobar que efectivamente tenemos acceso a la documentación de SwingExtras.jar. Esto se traduce en varias ventajas:
- si empezamos a escribir la instrucción de importación
, se observará que JBuilder nos ofrece ayuda:

El paquete com.lamatek se ha encontrado correctamente.
- Si ahora pasamos al siguiente programa:
Al introducir «F1» en la palabra clave «JFontChooser», se obtiene ayuda sobre esta clase:

En la barra de estado 1 se puede ver que, efectivamente, se está utilizando un archivo HTML del paquete swingextras.jar. El ejemplo anterior es lo suficientemente claro como para que podamos escribir el código del botón Police de nuestra aplicación:
void btnPolice_actionPerformed(ActionEvent e) {
// selección de una fuente de texto mediante el componente JFontChooser
jFontChooser1 = new JFontChooser(new Font("Arial", Font.BOLD, 12));
if (jFontChooser1.showDialog(this, "Choix d'une police") == JFontChooser.ACCEPT_OPTION) {
// se cambia la fuente de los caracteres del cuadro de texto
txtTexte.setFont(jFontChooser1.getSelectedFont());
}//si
}
El cuadro de selección que muestra el método showDialog anterior es el siguiente:

5.5. La aplicación gráfica IMPOTS
Retomamos la aplicación IMPOTS, que ya hemos tratado en dos ocasiones. Ahora le añadimos una interfaz gráfica:

Los controles son los siguientes
n.º | tipo | nombre | función |
1 | JRadioButton | rdOui | marcar si está casado |
2 | JRadioButton | rdNon | marcar si no está casado |
3 | JSpinner | spinEnfants | Número de hijos del contribuyente Mínimo=0, Máximo=20, Incremento=1 |
4 | JTextField | txtSalaire | salario anual del contribuyente en F |
5 | JLabel | lblImpots | Importe del impuesto a pagar |
6 | JTextField | txtStatus | Campo de mensajes de estado: no modificable |
El menú es el siguiente:
opción principal | opción secundaria | nombre | función |
Impuestos | |||
Inicializar | mnuInitialiser | carga los datos necesarios para el cálculo a partir de un archivo de texto | |
Calcular | mnuCalculer | calcula el impuesto a pagar cuando todos los datos necesarios están presentes y son correctos | |
Borrar | mnuEffacer | restablece el formulario a su estado inicial | |
Salir | mnuQuitter | cierra la aplicación |
Reglas de funcionamiento
- El menú Calculer permanece desactivado mientras no haya nada en el campo del salario
- si, al iniciar el cálculo, resulta que el salario es incorrecto, se señala el error:

A continuación se muestra el programa. Utiliza la clase impots creada en el capítulo sobre clases. No se ha reproducido aquí parte del código generado automáticamente por JBuilder.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.io.*;
import java.util.*;
import javax.swing.event.*;
public class frmImpots extends JFrame {
// los componentes de la ventana
JPanel contentPane;
JMenuBar jMenuBar1 = new JMenuBar();
JMenu jMenu1 = new JMenu();
JMenuItem mnuInitialiser = new JMenuItem();
JMenuItem mnuCalculer = new JMenuItem();
JMenuItem mnuEffacer = new JMenuItem();
JMenuItem mnuQuitter = new JMenuItem();
JLabel jLabel1 = new JLabel();
JFileChooser jFileChooser1 = new JFileChooser();
JTextField txtStatus = new JTextField();
JRadioButton rdOui = new JRadioButton();
JRadioButton rdNon = new JRadioButton();
JLabel jLabel2 = new JLabel();
JLabel jLabel3 = new JLabel();
JTextField txtSalaire = new JTextField();
JLabel jLabel4 = new JLabel();
JLabel jLabel5 = new JLabel();
JLabel lblImpots = new JLabel();
JLabel jLabel7 = new JLabel();
ButtonGroup buttonGroup1 = new ButtonGroup();
JSpinner spinEnfants=null;
FileFilter filtreTxt=null;
// los atributos de la clase
double[] limites=null;
double[] coeffr=null;
double[] coeffn=null;
impots objImpots=null;
//Crear el marco
public frmImpots() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
// otras inicializaciones
moreInit();
}
// inicialización del formulario
private void moreInit(){
// menú «Calcular» desactivado
mnuCalculer.setEnabled(false);
// campos de entrada desactivados
txtSalaire.setEditable(false);
txtSalaire.setBackground(Color.WHITE);
// campo de estado
txtStatus.setBackground(Color.WHITE);
// selector «Hijos»: entre 0 y 20 hijos
spinEnfants=new JSpinner(new SpinnerNumberModel(0,0,20,1));
spinEnfants.setBounds(new Rectangle(137,60,40,27));
contentPane.add(spinEnfants);
// filtro *.txt para el cuadro de selección
filtreTxt = new javax.swing.filechooser.FileFilter(){
public boolean accept(File f){
// ¿Se acepta «f»?
return f.getName().toLowerCase().endsWith(".txt");
}//aceptar
public String getDescription(){
// descripción del filtro
return "Fichiers Texte (*.txt)";
}//getDescription
};
// se añade el filtro *.txt
jFileChooser1.addChoosableFileFilter(filtreTxt);
// también queremos el filtro para todos los archivos
jFileChooser1.setAcceptAllFileFilterUsed(true);
// se establece el directorio de origen del buzón FileChooser
jFileChooser1.setCurrentDirectory(new File("."));
}//moreInit
//Inicializar el componente
private void jbInit() throws Exception {
................
}
//Sustituido, así podemos salir cuando se cierre la ventana
protected void processWindowEvent(WindowEvent e) {
.....................
}
void mnuQuitter_actionPerformed(ActionEvent e) {
// salimos de la aplicación
System.exit(0);
}
void mnuInitialiser_actionPerformed(ActionEvent e) {
// se carga el archivo de datos
// que se selecciona con el cuadro de selección JFileChooser1
jFileChooser1.setFileFilter(filtreTxt);
if (jFileChooser1.showOpenDialog(this)!=JFileChooser.APPROVE_OPTION)
return;
// se procesa el archivo seleccionado
try{
// lectura de datos
lireFichier(jFileChooser1.getSelectedFile());
// creación del objeto «impuestos»
objImpots=new impots(limites,coeffr,coeffn);
// confirmación
txtStatus.setText("Données chargées");
// el salario se puede modificar
txtSalaire.setEditable(true);
// No se pueden realizar más cambios
mnuInitialiser.setEnabled(false);
}catch(Exception ex){
// problema
txtStatus.setText("Erreur : " + ex.getMessage());
// fin
return;
}//captura
}
private void lireFichier(File fichier) throws Exception {
// las tablas de datos
ArrayList aLimites=new ArrayList();
ArrayList aCoeffR=new ArrayList();
ArrayList aCoeffN=new ArrayList();
String[] champs=null;
// apertura del archivo en modo lectura
BufferedReader IN=new BufferedReader(new FileReader(fichier));
// se lee el archivo línea por línea
// tienen la forma límite coeffr coeffn
String ligne=null;
int numLigne=0; // N.º de línea actual
while((ligne=IN.readLine())!=null){
// una línea más
numLigne++;
// se descompone la línea en campos
champs=ligne.split("\\s+");
// ¿3 campos?
if(champs.length!=3)
throw new Exception("ligne " + numLigne + "erronée dans fichier des données");
// se recuperan los tres campos
aLimites.add(champs[0]);
aCoeffR.add(champs[1]);
aCoeffN.add(champs[2]);
}//while
// cierre del archivo
IN.close();
// transferencia de los datos a matrices delimitadas
int n=aLimites.size();
limites=new double[n];
coeffr=new double[n];
coeffn=new double[n];
for(int i=0;i<n;i++){
limites[i]=Double.parseDouble((String)aLimites.get(i));
coeffr[i]=Double.parseDouble((String)aCoeffR.get(i));
coeffn[i]=Double.parseDouble((String)aCoeffN.get(i));
}//for
}
void mnuCalculer_actionPerformed(ActionEvent e) {
// cálculo del impuesto
// verificación del salario
int salaire=0;
try{
salaire=Integer.parseInt(txtSalaire.getText().trim());
if(salaire<0) throw new Exception();
}catch (Exception ex){
// mensaje de error
txtStatus.setText("Salaire incorrect. Recommencez");
// foco en el campo erróneo
txtSalaire.requestFocus();
// volver a la interfaz
return;
}
// número de hijos
Integer InbEnfants=(Integer)spinEnfants.getValue();
// cálculo de los impuestos
lblImpots.setText(""+objImpots.calculer(rdOui.isSelected(),InbEnfants.intValue(),salaire));
// borrado del mensaje de estado
txtStatus.setText("");
}
void txtSalaire_caretUpdate(CaretEvent e) {
// el salario ha cambiado: se actualiza el menú «Calcular»
mnuCalculer.setEnabled(! txtSalaire.getText().trim().equals(""));
}
void mnuEffacer_actionPerformed(ActionEvent e) {
// borrado del formulario
rdNon.setSelected(true);
spinEnfants.getModel().setValue(new Integer(0));
txtSalaire.setText("");
mnuCalculer.setEnabled(false);
lblImpots.setText("");
}
}
Aquí hemos utilizado un componente disponible a partir de la versión 1.4 de JDK, el JSpinner. Se trata de un incrementador que, en este caso, permite al usuario establecer el número de hijos. Este componente Swing no estaba disponible en la barra de componentes Swing de JBuilder 6, utilizada para la prueba. Esto no impide su uso, aunque el proceso resulte un poco más complicado que con los componentes disponibles en la barra de componentes. De hecho, no se puede colocar el componente JSpinner en el formulario durante el diseño. Hay que hacerlo en tiempo de ejecución. Veamos el código que lo hace:
// Control de carga «Hijos»: entre 0 y 20 hijos
spinEnfants=new JSpinner(new SpinnerNumberModel(0,0,20,1));
spinEnfants.setBounds(new Rectangle(137,60,40,27));
contentPane.add(spinEnfants);
La primera línea crea el componente JSpinner. Este componente puede utilizarse para diversas cosas, no solo como un incrementador de números enteros, como en este caso. El argumento del constructor JSpinner es, en este caso, un modelo de incrementador de números que admite cuatro parámetros (valor, mínimo, máximo e incremento). El componente tiene la siguiente forma:
![]()
valeur | valor inicial mostrado en el componente |
min | valor mínimo que se puede mostrar en el componente |
max | valor máximo que se puede mostrar en el componente |
incrément | valor de incremento del valor mostrado al utilizar las flechas arriba/abajo del componente |
El valor del componente se obtiene mediante su método getValue, que devuelve un tipo Object. De ahí que haya que realizar algunas conversiones de tipo para obtener el entero que necesitamos:
// Número de hijos
Integer InbEnfants=(Integer)spinEnfants.getValue();
// Cálculo de los impuestos
lblImpots.setText(""+objImpots.calculer(rdOui.isSelected(),
InbEnfants.intValue(),salaire));
Una vez definido el componente JSpinner, se coloca en la ventana:
Antes de nada, el usuario debe utilizar la opción de menú Initialiser, que crea un objeto impots con el constructor
de la clase impots. Recordemos que esta clase se definió a modo de ejemplo en el capítulo dedicado a las clases. Se puede consultar dicho capítulo si es necesario. Las tres tablas necesarias para el constructor se rellenan a partir del contenido de un archivo de texto con el siguiente formato:
12620.0 | 0 | 0 |
13190 | 0,05 | 631 |
15 640 | 0,1 | 1290,5 |
24 740 | 0,15 | 2072,5 |
31 810 | 0,2 | 3309,5 |
39 970 | 0,25 | 4900 |
48 360 | 0,3 | 6898,5 |
55 790 | 0,35 | 9316,5 |
92 970 | 0,4 | 12 106 |
127 860 | 0,45 | 16 754,5 |
151 250 | 0,50 | 23 147,5 |
172 040 | 0,55 | 30 710 |
195 000 | 0,60 | 39 312 |
0 | 0,65 | 49 062 |
Cada línea contiene tres números separados por al menos un espacio. El usuario selecciona este archivo de texto mediante un componente JFileChooser. Una vez creado el objeto de tipo impots, solo queda dejar que el usuario introduzca los tres datos necesarios: si está casado o no, el número de hijos y el salario anual, y llamar al método calculer de la clase impots. La operación se puede repetir varias veces. El objeto de tipo impots, por su parte, solo se crea una vez, al utilizar la opción Initialiser.
5.6. Creación de applets
5.6.1. Introducción
Cuando se ha escrito una aplicación con interfaz gráfica, resulta bastante sencillo convertirla en applet. Almacenada en un equipo A, esta puede descargarse mediante un navegador web desde un equipo B a través de Internet. De este modo, la aplicación inicial se comparte entre numerosos usuarios, y ahí radica el principal interés de convertir una aplicación en un applet. Sin embargo, no todas las aplicaciones pueden transformarse de esta manera: para no perjudicar al usuario que utiliza un applet en su navegador, el entorno del applet está regulado:
- un applet no puede leer ni escribir en el disco del usuario
- solo puede comunicarse con el ordenador desde el que ha sido descargada por el navegador.
Se trata de restricciones importantes. Implican, por ejemplo, que una aplicación que necesite leer información de un archivo o una base de datos deberá solicitarla a través de una aplicación intermediaria situada en el servidor desde el que se ha descargado.
La estructura general de una aplicación web sencilla es la siguiente:

- el cliente solicita un documento HTML al servidor web, normalmente mediante un navegador. Este documento puede contener un applet que funcionará como una aplicación gráfica autónoma dentro del documento HTML mostrado por el navegador del cliente.
- Este applet podrá acceder a datos, pero solo a aquellos que se encuentren en el servidor web. No tendrá acceso ni a los recursos del equipo cliente en el que se ejecute ni a los de otros equipos de la red distintos de aquel desde el que se haya descargado.
5.6.2. La clase JApplet
5.6.2.1. Définition
Una aplicación puede descargarse mediante un navegador web si es una instancia de la clase java.applet.Applet o de la clase javax.swing.JApplet. Esta última deriva de la primera, que a su vez deriva de la clase Panel, la cual deriva de la clase Container. Una instancia de tipo Applet o JApplet, al ser de tipo container, podrá contener, por tanto, componentes (Component) tales como botones, casillas de selección, listas, etc. Veamos algunas indicaciones sobre la función de los distintos métodos:
Método | Función |
public void destroy(); | destruye la instancia del applet |
public AppletContext getAppletContext(); | obtiene el contexto de ejecución del applet (el documento HTML en el que se encuentra, otros applets del mismo documento, etc.) |
public String getAppletInfo(); | devuelve una cadena de caracteres que proporciona información sobre el applet |
public AudioClip getAudioClip(URL url); | carga el archivo de audio especificado por URL |
public AudioClip getAudioClip(URL url, String name); | carga el archivo de audio especificado por URL/name |
public URL getCodeBase(); | devuelve el URL del applet |
public URL getDocumentBase(); | devuelve el URL del documento HTML que contiene el applet |
public Image getImage(URL url); | obtiene la imagen especificada por URL |
public Image getImage(URL url, String name); | recoge la imagen especificada por URL/name |
public String getParameter(String name); | obtiene el valor del parámetro name contenido en la etiqueta <applet> del documento HTML que contiene el applet. |
public void init(); | Este método lo inicia el navegador al ejecutar el applet por primera vez |
public boolean isActive(); | Estado del applet |
public void play(URL url); | Reproduce el archivo de sonido especificado por URL |
public void play(URL url, String name); | reproduce el archivo de sonido especificado por UR/name |
public void resize(Dimension d); | establece el tamaño del marco del applet |
public void resize(int width, int height); | lo mismo |
public final void setStub(AppletStub stub); | |
public void showStatus(String msg); | muestra un mensaje en la barra de estado del applet |
public void start(); | el navegador ejecuta este método cada vez que se muestra el documento que contiene el applet |
public void stop(); | el navegador ejecuta este método cada vez que se abandona el documento que contiene el applet para pasar a otro (cambio de URL por parte del usuario) |
La clase JApplet ha aportado algunas mejoras a la clase Applet, en particular la capacidad de contener componentes JMenuBar y c.a.d. de los menús, algo que no era posible con la clase Applet.
5.6.2.2. Ejecución de un applet: los métodos init, start y stop
Cuando un navegador carga un applet, invoca tres métodos del mismo:
init | Este método se invoca durante la carga inicial del applet. Por lo tanto, en él se incluirán las inicializaciones necesarias para la aplicación. |
start | Este método se invoca cada vez que el documento que contiene el applet se convierte en el documento activo del navegador. Así, cuando un usuario carga un applet, los métodos init y start se ejecutarán en ese orden. Cuando salga del documento para visualizar otro, se ejecutará el método stop. Cuando vuelva a él más tarde, se ejecutará el método start. |
stop | Este método se invoca cada vez que el usuario abandona el documento que contiene el applet. |
Para muchos applets, solo es necesario el método init. Los métodos start y stop solo son necesarios si la aplicación inicia tareas (hilos) que se ejecutan en paralelo y de forma continua, a menudo sin que el usuario se dé cuenta. Cuando el usuario sale del documento, la parte visible de la aplicación desaparece, pero estas tareas en segundo plano siguen funcionando. A menudo, esto es innecesario. Por lo tanto, se aprovecha la llamada del navegador al método stop para detenerlas. Si el usuario vuelve al documento, se aprovecha la llamada del navegador al método start para reiniciarlas.
Tomemos, por ejemplo, un applet que tiene un reloj en su interfaz gráfica. Este reloj se mantiene mediante una tarea en segundo plano (hilo). Cuando el usuario sale de la página del applet en el navegador, no tiene sentido mantener el reloj, que ya se ha vuelto invisible: en el método «stop» del applet, se detendrá el hilo que gestiona el reloj. En el método «start», se volverá a iniciar para que, cuando el usuario vuelva a la página del applet, encuentre un reloj que marque la hora correcta.
5.6.3. Transformación de una aplicación gráfica en un applet
Suponemos aquí que esta transformación es posible, es decir, que cumple con las restricciones de ejecución de los applets. Una aplicación se inicia mediante el método main de una de sus clases:
Una aplicación de este tipo se convierte en un applet de la siguiente manera:
import java.applet.JApplet;
…
public class application extends JApplet{
…
public void init(){
…
}
…
}// fin de clase
Cabe destacar lo siguiente:
- la clase application deriva ahora de la clase JApplet
- el método main se sustituye por el método init.
A modo de ejemplo, volvemos a una aplicación ya estudiada: la gestión de listas.

Los componentes de esta ventana son los siguientes:
n.º | tipo | nombre | función |
1 | JTextField | txtSaisie | campo de entrada |
2 | JList | jList1 | lista contenida en un contenedor jScrollPane1 |
3 | JList | jList2 | lista contenida en un contenedor jScrollPane2 |
4 | JButton | cmd1To2 | transfiere los elementos seleccionados de la lista 1 a la lista 2 |
5 | JButton | cmd2To1 | hace lo contrario |
6 | JButton | cmdRaz1 | vacía la lista 1 |
7 | JButton | cmdRaz2 | vacía la lista 2 |
La estructura de la aplicación era la siguiente:
public class interfaceAppli extends JFrame {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
JLabel jLabel2 = new JLabel();
JLabel jLabel3 = new JLabel();
JTextField txtSaisie = new JTextField();
JButton cmd1To2 = new JButton();
JButton cmd2To1 = new JButton();
DefaultListModel v1=new DefaultListModel();
DefaultListModel v2=new DefaultListModel();
JList jList1 = new JList(v1);
JList jList2 = new JList(v2);
JScrollPane jScrollPane1 = new JScrollPane();
JScrollPane jScrollPane2 = new JScrollPane();
JButton cmdRaz1 = new JButton();
JButton cmdRaz2 = new JButton();
JLabel jLabel4 = new JLabel();
/**Crear el marco*/
public interfaceAppli() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}//interfaceAppli
/**Inicializar el componente*/
private void jbInit() throws Exception {
...
txtSaisie.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
txtSaisie_actionPerformed(e);
}
});
...
// Jlist1 se coloca en el contenedor jScrollPane1
jScrollPane1.getViewport().add(jList1, null);
// Jlist2 se coloca en el contenedor jScrollPane2
jScrollPane2.getViewport().add(jList2, null);
...
}
/**Sustituido, para que podamos salir cuando se cierre la ventana*/
protected void processWindowEvent(WindowEvent e) {
...
}
void txtSaisie_actionPerformed(ActionEvent e) {
.............
}//clase
void cmdRaz1_actionPerformed(ActionEvent e) {
// vaciar lista 1
v1.removeAllElements();
}//comando Raz1
void cmdRaz2_actionPerformed(ActionEvent e) {
// vaciar lista 2
v2.removeAllElements();
}///cmd Raz2
Para transformar la clase appli en applet, hay que proceder de la siguiente manera:
- modificar la clase anterior interfaceAppli para que ya no derive de JFrame, sino de JApplet:
- eliminar la instrucción que establece el título de la ventana JFrame. Un applet JApplet no tiene barra de título
- Cambiar el constructor por un método init y, en dicho método, eliminar la gestión de eventos de ventana (WindowListener, ...). Un applet es un contenedor que no se puede redimensionar ni cerrar.
/**Crear el marco*/
public init() {
// enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}//interfaceAppli
- El método processWindowEvent debe eliminarse o comentarse
/**Sustituido, para que podamos salir cuando se cierre la ventana*/
//protected void processWindowEvent(WindowEvent e) {
// super.processWindowEvent(e);
// if (e.getID() == WindowEvent.WINDOW_CLOSING) {
// System.exit(0);
// }
// }
A modo de ejemplo, se muestra el código completo del applet, excepto la parte generada automáticamente por JBuilder
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class interfaceAppli extends JApplet {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
JLabel jLabel2 = new JLabel();
JLabel jLabel3 = new JLabel();
JTextField txtSaisie = new JTextField();
JButton cmd1To2 = new JButton();
JButton cmd2To1 = new JButton();
DefaultListModel v1=new DefaultListModel();
DefaultListModel v2=new DefaultListModel();
JList jList1 = new JList(v1);
JList jList2 = new JList(v2);
JScrollPane jScrollPane1 = new JScrollPane();
JScrollPane jScrollPane2 = new JScrollPane();
JButton cmdRaz1 = new JButton();
JButton cmdRaz2 = new JButton();
JLabel jLabel4 = new JLabel();
/**Crear el marco*/
public void init() {
// enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}//interfaceAppli
/**Inicializar el componente*/
private void jbInit() throws Exception {
//setIconImage(Toolkit.getDefaultToolkit().createImage(interfaceAppli.class.getResource("[Votre icône]")));
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(null);
this.setSize(new Dimension(400, 308));
// this.setTitle("JList");
jScrollPane1.setBounds(new Rectangle(37, 133, 124, 101));
jScrollPane2.setBounds(new Rectangle(232, 132, 124, 101));
.............
}
void txtSaisie_actionPerformed(ActionEvent e) {
// el texto introducido se ha validado
// se recupera sin los espacios iniciales y finales
String texte=txtSaisie.getText().trim();
// si está vacío, no lo queremos
if(texte.equals("")){
// mensaje de error
JOptionPane.showMessageDialog(this,"Vous devez taper un texte",
"Erreur",JOptionPane.WARNING_MESSAGE);
// fin
return;
}//si
// si no está vacío, se añade a los valores de la lista 1
v1.addElement(texte);
// y se vacía el campo de entrada
txtSaisie.setText("");
}
void cmd1To2_actionPerformed(ActionEvent e) {
// transferencia de los elementos seleccionados de la lista 1 a la lista 2
transfert(jList1,jList2);
}//cmd1To2
private void transfert(JList L1, JList L2){
// transferencia de los elementos seleccionados de la lista 1 a la lista 2
// se recupera la tabla de índices de los elementos seleccionados en L1
int[] indices=L1.getSelectedIndices();
// ¿Hay que hacer algo?
if (indices.length==0) return;
// se recuperan los valores de L1
DefaultListModel v1=(DefaultListModel)L1.getModel();
// y los de L2
DefaultListModel v2=(DefaultListModel)L2.getModel();
for(int i=indices.length-1;i>=0;i--){
// se añaden a L2 los valores seleccionados en L1
v2.addElement(v1.elementAt(indices[i]));
// los elementos de L1 copiados en L2 deben eliminarse de L1
v1.removeElementAt(indices[i]);
}//para
}//transferencia
private void affiche(String message){
// muestra un mensaje
JOptionPane.showMessageDialog(this,message,
"Suivi",JOptionPane.INFORMATION_MESSAGE);
}// muestra
void cmd2To1_actionPerformed(ActionEvent e) {
// transfiere los elementos seleccionados de jList2 a jList1
transfert(jList2,jList1);
}//cmd2TO1
void cmdRaz1_actionPerformed(ActionEvent e) {
// vaciar la lista 1
v1.removeAllElements();
}//comando Raz1
void cmdRaz2_actionPerformed(ActionEvent e) {
// lista vacía 2
v2.removeAllElements();
}//comando Borrar2
}//clase
Se puede compilar el código fuente de este applet. Aquí lo hacemos con el JDK, sin el JBuilder.
E:\data\serge\Jbuilder\interfaces\JApplets\1>javac.bat interfaceAppli.java
E:\data\serge\Jbuilder\interfaces\JApplets\1>dir
12/06/2002 16:40 6 148 interfaceAppli.java
12/06/2002 16:41 527 interfaceAppli$1.class
12/06/2002 16:41 525 interfaceAppli$2.class
12/06/2002 16:41 525 interfaceAppli$3.class
12/06/2002 16:41 525 interfaceAppli$4.class
12/06/2002 16:41 525 interfaceAppli$5.class
12/06/2002 16:41 4 759 interfaceAppli.class
La aplicación se puede probar con el programa AppletViewer de JDK, que permite ejecutar applets o un navegador. Para ello, hay que crear el documento HTML appli.htm, que contendrá el applet:
<html>
<head>
<title>listes swing</title>
</head>
<body>
<applet
code="interfaceAppli.class"
width="400"
height="300">
</applet>
</body>
</html>
Se trata de un documento HTML clásico, salvo por la presencia de la etiqueta «applet». Esta se ha utilizado con tres parámetros:
code="interfaceAppli.class" | nombre de la clase JAVA compilada que hay que cargar para ejecutar el applet |
width="400" | ancho del marco del applet en el documento |
height="300" | altura del marco del applet en el documento |
Una vez creado el archivo appli.htm, se puede cargar con el programa appletviewer de JDK o con un navegador. En una ventana de DOS, se escribe el siguiente comando en la carpeta del archivo appli.htm:
appletviewer appli.htm
Se supone aquí que el directorio del ejecutable appletviewer.exe se encuentra en el directorio PATH de la ventana de DOS; de lo contrario, habría que indicar la ruta completa del ejecutable appletviewer.exe. Aparecerá la siguiente ventana:

Detendremos la ejecución del applet con la opción Applet/Quitter. Probemos ahora el applet con un navegador. Este debe utilizar una máquina virtual Java 2 para poder mostrar los componentes Swing. Hasta hace poco (2001), esta restricción suponía un problema, ya que Sun producía JDK que los fabricantes de navegadores no incorporaban hasta mucho más tarde. Finalmente, Sun puso fin a este obstáculo poniendo a disposición de los usuarios una aplicación denominada «Java plugin», que permite a los navegadores Internet Explorer y Netscape Navigator utilizar las últimas versiones de JRE producidas por Sun (JRE = Java Runtime Environment). Las pruebas que se describen a continuación se han realizado con IE 5.5, equipado con el plugin Java 1.4.
Una primera forma de probar el applet interfaceAppli.class es cargar el archivo HTML appli.htm directamente en el navegador haciendo doble clic sobre él. El navegador mostrará entonces la página HTML y su applet sin necesidad de un servidor web:

Según el URL (1), se observa que el archivo se ha cargado directamente en el navegador. En el siguiente ejemplo, el archivo appli.htm se ha solicitado a un servidor web Apache que funciona en el puerto 81 del equipo local:

5.6.4. La opción de formato <applet> en un documento HTML
Hemos visto que, en un documento HTML, el applet se referenciaba mediante la etiqueta de formato <applet>. Esta etiqueta puede tener varios parámetros:
<applet
code=
width=
height=
codebase=
align=
hspace=
vspace=
alt=
>
<param name1=nom1 value=val1>
<param name2=nom2 value=val2>
texte
>
</applet>
El significado de los parámetros es el siguiente:
Parámetro | Significado |
code | obligatorio: nombre del archivo .class que se va a ejecutar |
width | obligatorio: ancho del applet en el documento |
height | obligatorio: altura… |
codebase | opcional: URL del directorio que contiene el applet que se va a ejecutar. Si no se especifica «codebase», el applet se buscará en el directorio del documento HTML que lo referencia |
align | opcional: posición (LEFT, RiGHT, CENTER) del applet en el documento |
hspace | opcional: margen horizontal que rodea el applet, expresado en píxeles |
vspace | opcional: margen vertical que rodea el applet, expresado en píxeles |
alt | opcional: texto que se muestra en lugar del applet si el navegador no puede cargarlo |
param | opcional: parámetro pasado al applet que especifica su nombre (name) y su valor (value). El applet podrá recuperar el valor del parámetro «nombre1» mediante «val1=getParameter("nombre1")» Se pueden utilizar tantos parámetros como se desee |
texte | Opcional: se mostrará en cualquier navegador que no pueda ejecutar un applet, por ejemplo, porque no dispone de una máquina virtual Java. |
Veamos un ejemplo para ilustrar el paso de parámetros a un applet:
<html>
<head>
<title>paramètres applet</title>
</head>
<body>
<applet code="interfaceParams.class" width="400" height="300">
<param name="param1" value="val1">
<param name="param2" value="val2">
</applet>
</body>
</html>
El código Java del applet interfaceParams se ha generado tal y como se ha indicado anteriormente. Se ha creado una aplicación JBuilder y, a continuación, se han realizado las transformaciones mencionadas anteriormente:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class interfaceParams extends JApplet {
JPanel contentPane;
JScrollPane jScrollPane1 = new JScrollPane();
JLabel jLabel1 = new JLabel();
DefaultListModel params=new DefaultListModel();
JList lstParams = new JList(params);
//Construir el marco
public void init() {
// enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
// otras inicializaciones
moreInit();
}
// inicializaciones
public void moreInit(){
// muestra los valores de los parámetros del applet
params.addElement("nom=param1 valeur="+getParameter("param1"));
params.addElement("nom=param2 valeur="+getParameter("param2"));
}//más inicializaciones
//Inicializar el componente
private void jbInit() throws Exception {
............
this.setSize(new Dimension(205, 156));
//this.setTitle("Parámetros de un applet");
jScrollPane1.setBounds(new Rectangle(19, 53, 160, 73));
............
}
}
La ejecución con AppletViewer:

5.6.5. Acceder a recursos remotos desde un applet
Muchas aplicaciones necesitan utilizar información contenida en archivos o bases de datos. Ya hemos señalado que un applet no tiene acceso a los recursos del equipo en el que se ejecuta. Se trata de una medida de sentido común. De lo contrario, bastaría con escribir un applet para «espiar» el disco de quienes lo cargan. No obstante, el applet sí tiene acceso a los recursos del servidor desde el que se ha descargado, por ejemplo, a los archivos. Esto es lo que vamos a ver ahora.
5.6.5.1. La clase URL
Cualquier aplicación Java puede leer un archivo presente en un equipo de la red gracias a la clase java.net.URL (URL = Uniform Resource Locator). Un URL identifica un recurso de la red, el equipo en el que se encuentra, así como el protocolo y el puerto de comunicación que hay que utilizar para recuperarlo, con el siguiente formato:
protocolo:puerto//ordenador/archivo
Así, el URL http://www.ibm.com/index.html hace referencia al archivo index.html de la máquina www.ibm.com. Se puede acceder a él mediante el protocolo http. No se especifica el puerto: el navegador utilizará el puerto 80, que es el puerto predeterminado del servicio http.
Veamos con más detalle algunos de los elementos de la clase URL:
public URL(String spec) | crea una instancia de URL a partir de una cadena del tipo «protocolo:puerto//máquina/archivo»; lanza una excepción si la sintaxis de la cadena no se corresponde con una URL |
public String getFile() | permite obtener el campo «archivo» de la cadena «protocolo:puerto//máquina/archivo» de URL |
public String getHost() | permite obtener el campo «máquina» de la cadena «protocolo:puerto//máquina/archivo» del URL |
public String getPort() | permite obtener el campo «puerto» de la cadena «protocolo:puerto//máquina/archivo» del URL |
public String getProtocol() | permite obtener el campo «protocolo» de la cadena «protocolo:puerto//máquina/archivo» del URL |
public URLConnection openConnection() | abre la conexión con el equipo remoto getHost() en su puerto getPort() según el protocolo getProtocol() con el fin de leer el archivo getFile(). Lanza una excepción si no se ha podido establecer la conexión |
public final InputStream openStream() | Abreviatura de openConnection().getInputStream(). Permite obtener un flujo de entrada a partir del cual se podrá leer el contenido del archivo getFile(). Lanza una excepción si no se ha podido obtener el flujo |
public String toString() | muestra la identidad de la instancia de URL |
Aquí hay dos métodos que nos interesan:
- public URL(String spec) para especificar el archivo que se va a procesar
- public final InputStream openStream() para procesarlo
5.6.5.2. Un ejemplo de consola
Vamos a escribir un programa en Java, sin interfaz gráfica, encargado de mostrar en pantalla el contenido de un URL que se le pasa como parámetro. Una llamada de ejemplo podría ser la siguiente:
El programa es relativamente sencillo:
import java.net.*; // para la clase URL
import java.io.*; // para los flujos (stream)
public class urlcontenu{
// muestra el contenido de URL pasado como argumento
// este contenido debe ser texto para que sea legible
public static void main (String arg[]){
// comprobación de los argumentos
if(arg.length==0){
System.err.println("Syntaxe pg url");
System.exit(0);
}
try{
// creación de URL
URL url=new URL(arg[0]);
// lectura del contenido
try{
// creación del flujo de entrada
BufferedReader is=new BufferedReader(new InputStreamReader(url.openStream()));
try{
// lectura de las líneas de texto en el flujo de entrada
String ligne;
while((ligne=is.readLine())!=null)
System.out.println(ligne);
} catch (Exception e){
System.err.println("Erreur lecture : " +e);
}
finally{
try { is.close(); } catch (Exception e) {}
}
} catch (Exception e){
System.err.println("Erreur openStream : " +e);
}
} catch (Exception e){
System.err.println("Erreur création URL : " +e);
}
}// fin de main
}// fin de clase
Tras comprobar que efectivamente hay un argumento, se intenta crear un URL con dicho argumento:
// creación de URL
URL url=new URL(arg[0]);
Esta creación puede fallar si el argumento no respeta la sintaxis de los URL protocole:port//machine/fichier. Si se dispone de un URL sintácticamente correcto, se intenta crear un flujo de entrada a partir del cual se puedan leer líneas de texto. El flujo de entrada proporcionado por una función URL URL.openStream() proporciona un flujo de tipo InputStream, que es un flujo orientado a caracteres: la lectura se realiza carácter por carácter y hay que formar las líneas uno mismo. Para poder leer líneas de texto, hay que utilizar el método readLine de las clases BufferedReader o DataInputStream.On; en este caso se ha elegido BufferedReader. Solo nos queda transformar el flujo InputStream de URL en el flujo BufferedReader. Esto se hace creando un flujo intermedio InputStreamReader:
BufferedReader is=new BufferedReader(new InputStreamReader(url.openStream()));
La creación de este flujo puede fallar. Se gestiona la excepción correspondiente. Una vez obtenido el flujo, solo nos queda leer las líneas de texto que contiene y mostrarlas en pantalla.
String ligne;
while((ligne=is.readLine())!=null)
System.out.println(ligne);
Una vez más, la lectura puede provocar una excepción que debe gestionarse. A continuación se muestra un ejemplo de ejecución del programa que requiere una URL local:
E:\data\serge\Jbuilder\interfaces\JApplets\3>java urlcontenu http://localhost
<html>
<head>
<title>Bienvenue dans le Serveur Web personnel</title>
</head>
<body bgcolor="#FFFFFF" link="#0080FF" vlink="#0080FF"
topmargin="0" leftmargin="0">
<table border="0" cellpadding="0" cellspacing="0" width="100%"
bgcolor="#000000">
............
</table>
</center></div></td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
5.6.5.3. Un ejemplo gráfico
La interfaz gráfica será la siguiente:

Número | Nombre | Tipo | Función |
1 | txtURL | JTextField | URL: a leer |
2 | btnCharger | JButton | Botón para iniciar la reproducción de URL |
3 | JScrollPane1 | JScrollPane | panel deslizante |
4 | lstURL | JList | lista que muestra el contenido del URL solicitado |
Al ejecutarlo, obtenemos un resultado similar al del programa de consola:

El código relevante de la aplicación es el siguiente:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.net.*;
import java.io.*;
public class interfaceURL extends JFrame {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
JTextField txtURL = new JTextField();
JButton btnCharger = new JButton();
JScrollPane jScrollPane1 = new JScrollPane();
DefaultListModel lignes=new DefaultListModel();
JList lstURL = new JList(lignes);
//Crear el marco
public interfaceURL() {
..............
}
//Inicializar el componente
private void jbInit() throws Exception {
..............
}
//Sustituido, para que podamos salir cuando se cierre la ventana
protected void processWindowEvent(WindowEvent e) {
...................
}
void txtURL_caretUpdate(CaretEvent e) {
// establece el estado del botón «Cargar»
btnCharger.setEnabled(! txtURL.getText().trim().equals(""));
}
void btnCharger_actionPerformed(ActionEvent e) {
// muestra el contenido de URL en la lista
try{
afficherURL(txtURL.getText().trim());
}catch(Exception ex){
// muestra un error
JOptionPane.showMessageDialog(this,"Erreur : " + ex.getMessage(),"Erreur",JOptionPane.ERROR_MESSAGE);
}//try-catch
}
private void afficherURL(String strURL) throws Exception {
// muestra el contenido de URL y strURL en la lista
// No se gestiona ninguna excepción de forma específica. Simplemente se reenvían
// creación del URL
URL url=new URL(strURL);
// creación del flujo de entrada
BufferedReader IN=new BufferedReader(new InputStreamReader(url.openStream()));
// lectura de las líneas de texto en el flujo de entrada
String ligne;
while((ligne=IN.readLine())!=null)
lignes.addElement(ligne);
// cierre del flujo de lectura
IN.close();
}
}
5.6.5.4. Un applet
La aplicación gráfica anterior se transforma en un applet, tal y como se ha mostrado en varias ocasiones. El applet se inserta en un documento HTML appliURL.htm:
<html>
<head>
<title>Applet lisant une URL</title>
</head>
<body>
<h1>Applet lisant une URL</h1>
<applet
code="appletURL.class"
width="400"
height="300"
>
</applet>
</body>
</html>

En el ejemplo anterior, el navegador solicitó el archivo «URL» http://localhost:81/Japplets/2/appliURL.htm a un servidor web «apache» que funciona en el puerto 81. A continuación, el applet se mostró en el navegador. En ella, se volvió a solicitar el archivo URL http://localhost:81/Japplets/2/appliURL.htm para comprobar que se obtenía efectivamente el archivo appliURL.htm que habíamos creado. Ahora intentemos cargar un archivo URL que no pertenezca al equipo que ha generado el applet (en este caso, localhost):

Se ha rechazado la carga del archivo URL. Aquí nos encontramos de nuevo con la restricción propia de los applets: solo pueden acceder a los recursos de red del equipo desde el que se han descargado. Existe una forma de que el applet eluda esta restricción, que consiste en delegar las solicitudes de red a un programa servidor ubicado en el equipo desde el que se ha descargado. Este programa realizará las solicitudes de red en lugar del applet y le enviará los resultados. A esto se le denomina programa relé.
5.7. El applet IMPOTS
Ahora vamos a convertir la aplicación gráfica IMPOTS en un applet. Esto tiene cierto interés: la aplicación estará disponible para cualquier usuario de Internet que disponga de un navegador y del plugin de Java 1.4 (gracias al componente JSpinner). De este modo, nuestra aplicación se vuelve global... Esta modificación requerirá algo más que la simple transformación de aplicación gráfica a applet, que ya se ha convertido en algo habitual. La aplicación utiliza una opción de menú Initialiser cuyo objetivo es leer el contenido de un archivo local. Sin embargo, si nos imaginamos una aplicación web, vemos que este esquema ya no es válido:

Es evidente que los datos que definen las escalas impositivas estarán en el servidor web y no en cada uno de los equipos cliente. El archivo que hay que leer en el servidor web se colocará aquí en la misma carpeta que el applet, y la opción Initialiser deberá ir a buscarlo allí. Los ejemplos anteriores han mostrado cómo hacerlo. Por otra parte, para seleccionar el archivo de datos localmente, se había utilizado un componente JFileChooser que ya no tiene sentido aquí.
El documento HTML que contiene el applet será el siguiente:
<html>
<head>
<title>Applet de calcul d'impôts</title>
</head>
<body>
<h2>Calcul d'impôts</h2>
<applet
code="appletImpots.class"
width="320"
height="270"
>
<param name="data" value="impots.txt">
Cabe destacar el parámetro data, cuyo valor es el nombre del archivo que contiene los datos de la escala impositiva. El documento HTML, la clase appletImpots, la clase impots y el archivo impots.txt se encuentran todos en la misma carpeta del servidor web:
E:\data\serge\web\JApplets\impots>dir
12/06/2002 13:24 247 impots.txt
13/06/2002 10:17 654 appletImpots$2.class
13/06/2002 10:17 653 appletImpots$3.class
13/06/2002 10:17 653 appletImpots$4.class
13/06/2002 10:17 651 appletImpots$5.class
13/06/2002 10:06 651 appletImpots$6.class
13/06/2002 10:17 8 655 appletImpots.class
13/06/2002 10:17 657 appletImpots$1.class
13/06/2002 10:24 286 appletImpots.htm
13/06/2002 10:17 1 305 impots.class
El código del applet es el siguiente (solo hemos resaltado los cambios respecto a la aplicación gráfica):
...........
import java.net.*;
import java.applet.Applet;
public class appletImpots extends JApplet {
// los componentes de la ventana
JPanel contentPane;
............................
// los atributos de la clase
double[] limites=null;
double[] coeffr=null;
double[] coeffn=null;
impots objImpots=null;
String urlDATA=null;
//Crear el marco
public void init() {
//enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
// otras inicializaciones
moreInit();
}
// inicialización del formulario
private void moreInit(){
// menú «Calcular» desactivado
mnuCalculer.setEnabled(false);
................
// se recupera el nombre del archivo de la tabla de impuestos
String nomFichier=getParameter("data");
// ¿Error?
if(nomFichier==null){
// mensaje de error
txtStatus.setText("Le paramètre data de l'applet n'a pas été initialisé");
// Se bloquea la opción «Inicializar»
mnuInitialiser.setEnabled(false);
// fin
return;
}//si
// se establece el URL de los datos
urlDATA=getCodeBase()+"/"+nomFichier;
}//moreInit
//Inicializar el componente
private void jbInit() throws Exception {
...................
}
void mnuQuitter_actionPerformed(ActionEvent e) {
// Se sale de la aplicación
System.exit(0);
}
void mnuInitialiser_actionPerformed(ActionEvent e) {
// se carga el archivo de datos
try{
// lectura de datos
lireDATA();
// creación del objeto «impuestos»
objImpots=new impots(limites,coeffr,coeffn);
................
}
private void lireDATA() throws Exception {
// las tablas de datos
ArrayList aLimites=new ArrayList();
ArrayList aCoeffR=new ArrayList();
ArrayList aCoeffN=new ArrayList();
String[] champs=null;
// apertura del archivo en modo lectura
BufferedReader IN=new BufferedReader(new InputStreamReader(new URL(urlDATA).openStream()));
// se lee el archivo línea por línea
....................
}
void mnuCalculer_actionPerformed(ActionEvent e) {
// cálculo del impuesto
......................
}
void txtSalaire_caretUpdate(CaretEvent e) {
..........
}
void mnuEffacer_actionPerformed(ActionEvent e) {
...............
}
}
Aquí solo comentamos los cambios derivados del hecho de que el archivo de datos que se va a leer se encuentra ahora en un equipo remoto en lugar de en un equipo local:
El nombre del archivo de datos que se va a leer, URL, se obtiene mediante el siguiente código:
// se recupera el nombre del archivo de la tabla de impuestos
String nomFichier=getParameter("data");
// ¿Error?
if(nomFichier==null){
// mensaje de error
txtStatus.setText("Le paramètre data de l'applet n'a pas été initialisé");
// se desactiva la opción «Inicializar»
mnuInitialiser.setEnabled(false);
// fin
return;
}//si
// se establece el URL de los datos
urlDATA=getCodeBase()+"/"+nomFichier;
Recordemos que el nombre del archivo «impots.txt» se ha pasado al parámetro data del applet:
Por lo tanto, el código anterior comienza recuperando el valor del parámetro data y gestionando cualquier posible error. Si el valor de URL del documento HTML que contiene el applet es http://localhost:81/JApplets/impots/appletImpots.htm, el URL del archivo impots.txt será http://localhost:81/JApplets/impots/impots.txt. Tenemos que construir el nombre de este URL. El método getCodeBase() del applet proporciona el URL de la carpeta de donde se ha recuperado el documento HTML que contiene el applet, por lo que, en nuestro ejemplo, http://localhost:81/JApplets/impots. La siguiente instrucción permite, por tanto, construir el URL del archivo de datos:
En el método lireFichier(), que lee el contenido de URL y urlData, se encuentra la creación del flujo de entrada que permitirá leer los datos:
// apertura del archivo en modo lectura
BufferedReader IN=new BufferedReader(new InputStreamReader(new URL(urlDATA).openStream()));
A partir de ahí, ya no se puede distinguir si los datos proceden de un archivo remoto o local. A continuación se muestra un ejemplo de ejecución del applet:

5.8. Conclusión
En este capítulo se ha presentado
- una introducción a la creación de interfaces gráficas con JBuilder
- los componentes Swing más habituales
- la creación de applets
Recordaremos que
- el código generado por JBuilder se puede escribir a mano. Una vez obtenido este código de una forma u otra, basta con un simple JDK para ejecutarlo y JBuilder ya no es imprescindible.
- el uso de una herramienta como JBuilder puede suponer importantes ganancias de productividad:
- aunque sea posible escribir a mano el código generado por JBuilder, esto puede llevar mucho tiempo y tiene poco interés, ya que la lógica de la aplicación suele estar en otro lugar.
- El código generado puede resultar instructivo. Leerlo y estudiarlo es una buena forma de descubrir ciertos métodos y propiedades de los componentes que se utilizan por primera vez.
- JBuilder es multiplataforma. Por lo tanto, se conserva lo aprendido al pasar de una plataforma a otra. Poder escribir programas que funcionen tanto en Windows como en Linux es, por supuesto, un factor de productividad muy importante. Pero esto se debe a Java en sí mismo y no a JBuilder.
5.9. JBuilder en Linux
Todos los ejemplos anteriores se han probado en Windows 98. Cabe preguntarse si los programas escritos son portables tal cual a Linux. Siempre que el equipo con Linux en cuestión disponga de las clases utilizadas por los distintos programas, sí lo son. Si, por ejemplo, ha instalado JBuilder en Linux, las clases necesarias ya se encuentran en su equipo. A continuación se muestra, a modo de ejemplo, el resultado de la ejecución de uno de nuestros programas en el componente JList con JBuilder 4 en Linux:
A continuación, te explicamos cómo instalar JBuilder 4 Foundation en un equipo con Linux. Su instalación en un equipo con Win9x no plantea ningún problema y es similar al proceso que vamos a describir a continuación. Es probable que la instalación de versiones posteriores sea diferente, pero este documento puede ofrecerte, no obstante, alguna información útil.
JBuilder está disponible en la página web de Inprise en la URL http://www.inprise.com/jbuilder

En esta página se encuentran los enlaces para Windows y Linux, entre otros. A continuación describimos la instalación de JBuilder en un equipo Linux que cuenta con la interfaz gráfica KDE.
Al seguir el enlace «Jbuilder 4 for Linux», aparece un formulario. Lo rellenamos y, al final, obtenemos dos archivos:
jb4docs_fr.tar.gz: la documentación y los ejemplos de JBuilder 4
jb4fndlinux_fr.tar.gz: JBuilder 4 Foundation. Se trata de una versión limitada del JBuilder 4 comercial, pero suficiente en un contexto educativo.
Se te enviará por correo electrónico una clave de activación del software. Esta clave te permitirá utilizar JBuilder 4 y se te solicitará la primera vez que lo utilices. Si pierdes esta clave, puedes volver a la URL anterior y seguir el enlace «get your activation key». A partir de ahora, daremos por hecho que eres root y que te encuentras en el directorio de los dos archivos tar.gz mencionados anteriormente. Descomprime los dos archivos:
[ls -l]
drwxr-xr-x 3 nobody nobody 4096 oct 10 2000 docs
drwxr-xr-x 3 nobody nobody 4096 déc 5 13:00 foundation
[ls -l foundation]
-rw-r--r-- 1 nobody nobody 1128 déc 5 13:00 deploy.txt
-rwxr-xr-x 1 nobody nobody 69035365 déc 5 13:00 fnd_linux_install.bin
drwxr-xr-x 2 nobody nobody 4096 déc 5 13:00 images
-rw-r--r-- 1 nobody nobody 15114 déc 5 13:00 index.html
-rw-r--r-- 1 nobody nobody 23779 déc 5 13:00 license.txt
-rw-r--r-- 1 nobody nobody 75739 déc 5 13:00 release_notes.html
-rw-r--r-- 1 nobody nobody 31902 déc 5 13:00 whatsnew.html
[ls -l docs]
-rw-r--r-- 1 nobody nobody 1128 oct 10 2000 deploy.txt
-rwxr-xr-x 1 nobody nobody 40497874 oct 10 2000 doc_install.bin
drwxr-xr-x 2 nobody nobody 4096 oct 10 2000 images
-rw-r--r-- 1 nobody nobody 9210 oct 10 2000 index.html
-rw-r--r-- 1 nobody nobody 23779 oct 10 2000 license.txt
-rw-r--r-- 1 nobody nobody 75739 oct 10 2000 release_notes.html
-rw-r--r-- 1 nobody nobody 31902 oct 10 2000 whatsnew.html
En los dos directorios generados, el archivo .bin es el archivo de instalación. Además, abre con un navegador el archivo index.html de cada uno de los directorios. En ellos se indican los pasos a seguir para instalar ambos productos. Empecemos por instalar JBuilder Foundation:
Aparece la primera pantalla de la instalación. A continuación aparecerán muchas más:

Confirma. A continuación aparece una pantalla con explicaciones:

Ejecute [suivant].

Acepte el contrato de licencia y ejecute [suivant].

Acepta la ubicación propuesta para JBuilder (anótala, la necesitarás más adelante) y ejecuta [suivant]. La instalación se realiza rápidamente.

Ya estamos listos para una primera prueba. En KDE, abre el gestor de archivos para acceder al directorio de los ejecutables de JBuilder: /opt/jbuilder4/bin (si has instalado JBuilder en /opt/jbuilder4):

Haz clic en el icono jbuilder que aparece arriba. Como es la primera vez que utilizas JBuilder, tendrás que introducir tu clave de activación:

Rellene los campos Nom y Société. Pulsa [Ajouter] para introducir tu clave de activación. Recuerda que esta clave te la deben haber enviado por correo electrónico y que, si la has perdido, puedes recuperarla en la URL desde donde descargaste JBuilder 4 (véase el inicio de la instalación). Una vez aceptada tu clave de activación, se te recordarán las condiciones de la licencia:

Al introducir OK, volverá a la ventana de introducción de datos que ya ha visto:

Introduzca OK para finalizar esta fase, que solo se ejecuta la primera vez. A continuación, aparecerá el entorno de desarrollo de JBuilder:

Sal de JBuilder para instalar ahora la documentación. Esta instalará una serie de archivos que se utilizarán en la ayuda de JBuilder, ayuda que, por el momento, está incompleta. Vuelve al directorio donde has descomprimido los archivos tar.gz de JBuilder. El programa de instalación se encuentra en el directorio docs. Accede a él:
[cd docs]
[ls -l]
-rw-r--r-- 1 nobody nobody 1128 oct 10 2000 deploy.txt
-rwxr-xr-x 1 nobody nobody 40497874 oct 10 2000 doc_install.bin
drwxr-xr-x 2 nobody nobody 4096 oct 10 2000 images
-rw-r--r-- 1 nobody nobody 9210 oct 10 2000 index.html
-rw-r--r-- 1 nobody nobody 23779 oct 10 2000 license.txt
-rw-r--r-- 1 nobody nobody 75739 oct 10 2000 release_notes.html
-rw-r--r-- 1 nobody nobody 31902 oct 10 2000 whatsnew.html
El archivo de instalación es doc_install.bin, pero no se puede ejecutar inmediatamente. Si lo haces, la instalación fallará sin que se entienda por qué. Lee el archivo index.html con un navegador para obtener una descripción detallada del proceso de instalación. El instalador necesita una máquina virtual Java, concretamente un programa llamado java, que debe encontrarse en el directorio PATH de tu equipo. Recordamos que PATH es una variable de Unix cuyo valor, con el formato rep1:rep2:...:repn, indica los directorios repi que deben explorarse en la búsqueda de un ejecutable. En este caso, el instalador solicita la ejecución de un programa java. Puede que tengas varias versiones de este programa, dependiendo del número de máquinas virtuales Java que hayas instalado aquí o allá. Como es lógico, utilizaremos la que incluye JBuilder 4 y que se encuentra en /opt/jbuilder4/jdk1.3/bin. Para añadir este directorio a la variable PATH:
[echo $PATH]
/usr/local/sbin:/usr/sbin:/sbin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin
[export PATH=/opt/jbuilder4/jdk1.3/bin/:$PATH]
[echo $PATH]
/opt/jbuilder4/jdk1.3/bin/:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin
Ahora podemos iniciar la instalación de la documentación:
Se va a realizar una instalación gráfica:

Es muy similar a la de JBuilder Foundation. Por lo tanto, no la detallaremos. Hay una pantalla que no hay que pasarse por alto:

Normalmente, el instalador debería detectar automáticamente dónde has instalado JBuilder Foundation. Por lo tanto, no modifiques lo que te propone, salvo, por supuesto, que sea incorrecto.
Una vez instalada la documentación, estamos listos para realizar una nueva prueba de JBuilder. Ejecuta la aplicación tal y como se ha mostrado anteriormente. Una vez que JBuilder esté en marcha, selecciona la opción Ayuda/Tema de ayuda. En el panel de la izquierda, haz clic en el enlace Tutoriels:

JBuilder incluye un conjunto de tutoriales que te permitirán iniciarte en la programación en Java. A continuación hemos seguido el tutorial «Creación de una aplicación» mencionado anteriormente.

En JBuilder, selecciona Archivo/Nuevo proyecto. Un asistente te mostrará tres pantallas:

Vamos a crear una ventana sencilla con el título «Hola a todos». Llamaremos a este proyecto coucou. El ejemplo se ha ejecutado mediante root. A continuación, JBuilder propone agrupar todos los proyectos en un directorio jbproject dentro del directorio de conexión de root. El proyecto coucou se colocará en el directorio coucou (campo «Nombre del directorio del proyecto») de jbproject. Cree [suivant].

Esta segunda pantalla es un resumen de las diferentes rutas de su proyecto. No hay nada que modificar. Seleccione [suivant].

La tercera pantalla le pide que personalice su proyecto. Rellénela y pulse [Terminer].
Ahora ejecute Fichier/Nouveau:

Selecciona Application y ejecuta OK. Un nuevo asistente te mostrará dos pantallas:

El campo paquet recoge el nombre del proyecto. El campo «clase» solicita el nom que se asignará a la clase principal del proyecto. Tome el nombre anterior y introduzca [suivant]:

Nuestra aplicación incluye una segunda clase Java para la ventana de la aplicación. Asigna un nombre a esta clase. El campo Titre es el título que deseas asignar a esta ventana. El cuadro options te ofrece opciones para tu ventana. Selecciónalas todas y establece [Terminer]. A continuación, volverás al entorno JBuilder, que se habrá actualizado con la información que has proporcionado para tu proyecto:

En la ventana de la parte superior izquierda (1) aparece la lista de archivos que componen su proyecto. Entre ellos se encuentran las dos clases .java a las que acabamos de asignar un nombre. En la ventana de la derecha (2) aparece el código Java de la clase coucouCadre. En la ventana de la izquierda/parte inferior, aparece la estructura (clases, métodos, atributos) de su proyecto. Está listo para ejecutarse. Pulse el botón 4 de arriba, seleccione Ejecutar/Ejecutar el proyecto o seleccione F9. Debería aparecer la siguiente ventana:

Al hacer clic en la opción Aide, deberías encontrar la información que has proporcionado a los asistentes de creación. No vamos a seguir adelante. Ahora es el momento de sumergirte en los tutoriales.
Antes de terminar, veamos simplemente que puede utilizar, no JBuilder y su interfaz gráfica, sino el JDK que este ha traído consigo y que ha colocado en /opt/jbuilder4/jdk1.3. Compile el siguiente archivo essai1.java:
import java.io.*;
public class essai1{
public static void main(String args[]){
System.out.println("coucou");
System.exit(0);
}
}
Compilémoslo y ejecutémoslo con el JDK de JBuilder:






