====== Componentes Swing ======
A continuación examinamos diferentes componentes de Swing. Todas las referencias están obtenidas de la documentación oficial de Java: https://docs.oracle.com/javase/tutorial/uiswing/components/index.html
===== Contenedores de alto nivel =====
{{:bloque4:topleveldemometal.png?150 |}}
{{ :bloque4:conceptualpane.gif?280|}}
* **JFrame**: Ventana principal para una aplicación de escritorio. Contiene los botones de cerrar maximinar y minimizar. Cuando está en ejecución mantiene un elemento en la barra de tareas.
* **JApplet**: Ventana principal para una aplicación Web. Contiene los botones de cerrar maximinar y minimizar. Cuando está en ejecución mantiene un elemento en la barra de tareas. **Los applets están en desuso**.
* **JDialog**: Se usa para crear ventanas secundarias de dialogo. La diferencia respecto a los contenedores anteriores, es que no muestra un elemento en la barra de tareas. En la categoría de este tipo de contenedores tenemos JOptionPane cuadros de dialogo sencillos, o JFileChooser una ventana de dialogo para seleccionar ficheros. Si queremos crear un cuadro de dialogo personalizado usamos JDialog.
Cualquier programa tiene una jerarquía de contenedores, siendo JFrame, JApplet o JDialog la raíz de la jerarquía, ya que cada uno tendrá una clase propia donde será definido. Si una aplicación tiene 3 ventanas, tendrá 3 jerarquías de contendores y 3 contenedores de alto nivel (un JFrame y 2 JDialog).
A cada ventana podemos especificarle un título, un icono, y si la ventana será redimensionable o no, entre otras opciones que podemos establecer en las propiedades del elemento en la interfaz de WindowBuilder.
===== Contenedores de 2º nivel =====
==== Content Pane ====
Todo contenedor de alto nivel tiene un elemento ContentPane para emplazar el resto de componentes (etiquetas, cuadros de texto, botones, etc). El contentPane por defecto es un elemento **JPanel**, aunque podemos usar otros similares. Estos contenedores se conocen como contenedores de __segundo nivel__.
===== Layout =====
Todo ''contentPane'' tiene una organización para emplazar los elementos. Los tipos de organización son los ''Layouts''. Pulsando sobre cada uno de los siguientes enlaces, accedemos a su documentación:
* [[https://docs.oracle.com/javase/tutorial/uiswing/layout/none.html|AbsoluteLayout]]
* [[https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html#border|BorderLayout]]
* [[https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html#box|BoxLayout]]
* [[https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html#card|CardLayout]]
* [[https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html#flow|FlowLayout]]
* [[https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html#gridbag|GridBagLayout]]
* [[https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html#grid|GridLayout]]
* [[https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html#group|GroupLayout]]
* [[https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html#spring|SpringLayout]]
Para establecer un ''Layout'', basta con seleccionar alguno en la paleta y pulsar después sobre el contentPane de nuestra ventana. También podemos acceder a las propiedades del contentPane y seleccionarlo en la opción Layout.
**El layout más sencillo de usar es el ''AbsoluteLayout''**, con el que indicamos que realmente no usamos layout, y podemos emplazar los componentes donde queramos.
===== Manejadores de Eventos – Event Handlers =====
==== Eventos ====
Un evento es una acción, provocada en la mayoría de los casos por el usuario, y que supone un cambio en el estado de algún componente (por ejemplo, botón).
Los eventos, permiten llevar a cada la funcionalidad de las aplicaciones basadas en una GUI.
{{ :bloque4:addeventhandler.png?350|}}
Para que nuestro programa pueda responder (ejecutar código) ante un evento, debemos usar un manejador de eventos. Existen una gran cantidad de eventos diferentes, pero nos vamos a centrar en el evento que se provocará en la mayor parte de los casos, el clic de ratón: **ActionPerformed** (Acción realizada).
==== Añadir manejadores de eventos ====
Para añadir un manejador de eventos a nuestra aplicación, bastará con pulsar clic derecho sobre el elemento (p.e. botón) sobre el cual queremos controlar un evento. Se nos desplegará un menú en el que podemos seleccionar el evento que queremos controlar.
En algunos componentes deberemos crear un manejador de eventos para otro tipo de eventos (KeyEvent, StateChanged, p.e.), aunque como se ha comentado, en la mayoría de los casos bastará con el evento //actionPerformed//.
{{ :bloque4:addeventhandler2.png?300|}}
Cuando creemos un manejador de eventos, este se asociará al elemento sobre el cual se realiza el evento (p.e. botón).
Este código se creará justo debajo de la definición del componente, por lo que deberemos moverlo al lugar en el que lo queremos organizar (por ejemplo un método para inicializar los manejadores de eventos).
===== Barra de Menus - JMenuBar =====
{{ :bloque4:conceptualpane.gif?250|}}
{{ :bloque4:jmenubar.png?100|}}
Una aplicación está formada por un contenedor de alto nivel un contentPane y opcionalmente una barra de menú.
Normalmente una barra de menús solo aparece en las ventanas principales (JFrames).
https://docs.oracle.com/javase/tutorial/uiswing/components/menu.html
Para crear una barra de menú usaremos el elemento **JMenuBar**.{{ :bloque4:jmenucomponents.png?200|}}
Cada Pestaña desplegable de ese menú será un elemento **JMenu**.
Cada elemento de ese menú deplegable será un **JMenuItem**.
Además, podemos incluir elementos de tipo CheckBox, o RadioButtons.
Si queremos incluir una pestaña Salir, la instrucción que debemos ejecutar es: //System.exit(0)//.
__Eventos Principales:__ ''ActionPerformed''
===== Componentes para contenedores de 2º nivel =====
==== JLabel ====
{{ :bloque4:jlabel.png?150|}}
Se usa para mostrar una etiqueta con texto o con una imagen en nuestra aplicación.
Para incluir un texto o una imagen podemos usar las propiedades del JLabel:
* ''Text'': texto que muestra.
* ''Icon'': imagen que queremos que contenga.
__Métodos Principales__:
* ''setText(String texto)'' : Permite modificar el texto que muestra la etiqueta.
==== JButton ====
{{ :bloque4:jbuttons.png?100|}}
Hace referencia a un botón que puede ser pulsado. Los siguientes elementos hacen referencia a los botones y heredan de la clase AbstractButton:
* ''JButton'' : Botón convencional
* ''JToggleButton'' : Botón que puede estar presionado o no presionado.
* ''JCheckBox'' : Casilla de verificación
* ''JRadioButton'' : Parecido a la casilla de verificación. Tiene la peculiaridad que se suele usar alternativamente con otros JRadioButtons.
__Evento Principal__: ''ActionPerformed''
Además, los botones que pueden estar seleccionados o no (Checkbox, RadioButton), tienen dos métodos importantes para trabajar con ellos:
* ''isSelected()'' : devuelve true o false si está seleccionado o no.
* ''setSelected(boolean estado)'' : se usa para marcar o desmarcar el botón.
{{ :bloque4:buttongroup.png?350|}}
=== JRadioButton ===
En el caso de los ''JRadioButton'' es interesante permitir la selección de un solo botón entre varios del mismo tipo.
Para hacer esto seleccionaremos todos los elementos ''JRadioButton'' que queremos que estén agrupados y pulsamos botón derecho, opción ''Set ButtonGroup'' y creamos un nuevo grupo ''standard''.
----
==== JComboBox ====
{{:bloque4:jcombo.png?100 |}}
Elemento que permite seleccionar distintas opciones en un menú desplegable. Cuando creamos uno debemos establecer un modelo para él. En la sección de propiedades pulsaremos sobre la opción model y se nos desplegará una ventana en la que podremos indicar qué opciones queremos que tenga el ComboBox:
{{:bloque4:jcomboproperties.png?200 |}}
{{ :bloque4:jcombomodel.png?300 |}}
Es interesante remarcar que al modelo podemos añadirle elementos desde un array.
{{ :bloque4:jbombo4.png?100|}}
__Métodos principales__:
* ''getSelectedIndex()'' : devuelve un entero indicando el elemento seleccionado.
También permite ser usado con un modelo, que facilita el trabajo con los **objetos** que puede mostrar: Clase ''DefaultComboBoxModel''
==== JTextField ====
{{ :bloque4:jtextfield.png?200|}}
Cuadro de texto convencional. Puede contener un texto por defecto, mostrar texto u obtener texto para gestionarlo.
__Métodos principales__:
* ''setText(String texto)'' : Muestra el texto en el cuadro.
* ''getText()'' : Devuelve un String con el texto del cuadro.
==== JPasswordField ====
{{ :bloque4:jpassfield.png?200|}}
Es un cuadro de texto que no muestra los caracteres que se teclean.
__Métodos principales__:
* ''getPassword()'' : Devuelve un array de char con el texto del cuadro.
Si queremos convertir el array a String podemos usar el método estático ''String.valueOf(array)''.
==== JScrollPane ====
Se usa principalmente para que los elementos que contiene tengan barras de desplazamiento en caso de que su contenido supere las dimensiones de su contenedor.
{{ :bloque4:jtextareascroll.png?300|}}
Para usarlo simplemente crearemos un elemento ''JScrollPane'' en la ventana principal. Posteriormente emplazaremos dentro del JScrollPane el elemento que queramos que tenga barras de desplazamiento, por ejemplo un ''JList'', o un ''JTextArea''.
==== JTextArea ====
Funciona de la misma forma que un JTextField pero se usa para contener más cantidad de texto, o pasa mostrarlo.
Puede ser editable o no, lo que quiere decir que podremos escribir texto y modificarlo o no se podrá escribir desde teclado, y solo se mostrará desde el código de nuestro programa.
__Métodos principales__:
* ''setText(String texto)'' : Mostrará el texto que contiene el String que le pasamos.
* ''getText()'' : Devuelve un String con el texto que contiene.
* ''append(String texto)'' : Añade al cuadro más texto, sin eliminar el texto actual.
==== JSpinner ====
{{ :bloque4:jspinner.png?80|}}
Es un elemento similar a un ComboBox que permite seleccionar valores entre un rango. Permiten establecer un límite máximo y mínimo y un valor por defecto en sus propiedades.
__Métodos principales__:
* ''setValue(Object valor)'' : Establece un objeto como valor para el spinner. Si queremos indicar un número debes usar el tipo envoltorio Integer.
* ''getValue()'' : Devuelve el objeto con el valor establecido. Si se trata de un número debemos hacer un cast a int.
__Evento principal__: ''stateChanged'' - se produce cuando hay un cambio en su valor.
==== JSlider ====
{{:bloque4:jslider.png?150 |}}
Es una barra de desplazamiento para indicar valores numéricos dentro de un rango. Permite establecer un máximo, minimo, valor por defecto, y una escala, en sus propiedades.
{{ :bloque4:jsliderproperties.png?200|}}
Propiedades:
* ''majorTickSpacing'': sirve para indicar las etiquetas en las que se dividirá la barra del slider.
* ''Maximun'': límite superior.
* ''Minimun'': límite inferior.
* ''paintLabels'': true para que aparezca una leyenda de valores.
* ''Value'': valor por defecto con el que comienza.
__Métodos Principales__:
* ''setValue(int valor)'' : El slider se posiciona en dicho valor.
* ''getValue()'' : Devuelve un entero con el valor de su posición.
__Eventos__: ''stateChanged'' - se produce cuando hay un cambio en su valor.
=== Relacionar JSlider y JSpinner ===
Como son dos elementos usados de forma parecida podemos relacionarlos:
spinner.setValue(slider.getValue()); //Para el spinner
slider.setValue((int)spinner.getValue()); //Para el slider
==== JList ====
{{ :bloque4:jlist.png?300|}}
Es una lista de elementos de tipo objeto: Pueden ser Strings o cualquier tipo de objeto. Permite seleccionarlos, de uno en uno o varios a la vez. También se combina con JScrollBar para que tenga barras de desplazamiento.
La peculiaridad que tiene, al igual que los ComboBox o las tablas, es que trabaja con un modelo (Model), y también que es un elemento de tipo "Raw". Esto quiere decir que al igual que los ArrayLists p.e. se debe definir el tipo de datos que contiene.
Jlist lista = new JList();
Para trabajar con un JList de forma sencilla, se debe hacer uso de un elemento de tipo Model, el cual también es de tipo Raw.
Primero crearemos un Modelo para la lista y posteriormente trabajamos directamente con dicho modelo.
DefaultListModel listModel = new DefaultListModel();
JList listaPersonas = new JList(listModel);
listModel.addElement(new Persona("Jane Doe"));
listModel.addElement(new Persona("John Smith"));
listModel.addElement(new Persona("Kathy Green"));
Para añadir el contenido de un ArrayList:
Jlist lista = new JList();
DefaultListModel modelo = new DefaultListModel();
lista.setModel(modelo);
//Accedo a la lista de clientes, y añado sus elementos
for (Cliente miCliente : gestor.getListaClientes()) {
modelo.addElement(miCliente);
}
{{ :bloque4:jlistselectionmode.png?200|}}
Para obtener el directamente el **objeto** seleccionado:
lista.getSelectedValue()
En las propiedades del JList podemos indicar si queremos que se permitan seleccionar diferentes elementos o solo uno (''SINGLE_SELECTION'')
__Evento:__ ''ListSelectionEvent'' - se produce al seleccionar o deseleccionar elementos del JList
==== JProgressBar ====
Es una barra de progreso, se suele emplear para indicar el avance de las tareas.
{{:bloque4:jpreogressbar.png?150|}}
__Métodos principales__:
* ''setValue(int valor)'' : Establece el valor que mostrará la barra.
==== JSeparator ====
Se usa para separar partes de la ventana o para separar elementos en un JMenu.
{{:bloque4:jseparatormenu.png?80|}}
{{:bloque4:jseparator2.png?300 |}}
==== JTabbedPane ====
Permite crear un contenedor de pestañas, separando en cada pestaña los elementos que sean necesarios en cada caso.
{{:bloque4:jtabedpane_example.gif}}
Para crear un JTabbedPane con varias pestañas, debemos emplazar un elemento JTabbedPane en el lugar de nuestro contentPane en el que lo queramos. Posteriormente, para añadir pestañas simplemente añadiremos elementos de tipo JPanel a nuestro JTabbedPane.
{{ :bloque4:jtabbedpane2.png?350|}}
Cada una de las pestañas se trata igual que el ''contentPane'' principal (como un JPanel), por lo que **debemos asignarle un layout** y posteriormente colocar elementos en él.
Para modificar el nombre de las pestañas debemos ir al código de nuestra clase (imagen).
==== DatePicker ====
{{ :bloque4:jdatepicker.png?150|}}
Java no tiene un selector nativo de fechas (calendario) para Swing. Sin embargo, existen diversos proyectos particulares de componentes personalizados. Esto se conoce en Java como //JavaBeans//. Los JavaBeans o Beans son clases empaquetadas, reutilizables en nuestro código.
Para obtener un selector de fechas que trabaje con las clases del paquete ''java.time'' (LocalDate, LocalTime, LocalDateTime a partir de la versión 8 de Java) podemos usar el Bean creado por el proyecto ''LGoodDatePicker''.
Para usar los beans, debemos tener el fichero Jar con los componentes que queremos utilizar y añadirlo al ClassPath de nuestro proyecto como cualquier otro JAR. Posteriormente desde el editor gráfico de WindowBuilder, en la sección System pinchamos sobre //Choose component// y buscamos la clase DatePicker (LGoodDatePicker).
Una vez que podamos acceder a ese elemento bastará con arrastrarlo a la parte de nuestra ventana en la que queramos emplazarlo.
__Métodos__:
* ''getDate()'' : Devuelve un tipo LocalDate con la fecha seleccionada.
* ''setDate(LocalDate fecha)'' : Establece la fecha indicada en el DatePicker.
Links del proyecto:
https://mvnrepository.com/artifact/com.github.lgooddatepicker/LGoodDatePicker
Pulsamos sobre la versión que queramos y descargamos el fichero Jar.
==== JToolBar ====
Se usa para crear una barra de herramientas, con botones. Se añaden los botones y se tratan como JButtons.
https://docs.oracle.com/javase/tutorial/uiswing/components/toolbar.html
==== JTable ====
Se usa para mostrar la información mediante filas y columnas. Muy útil para cargar información de las tablas de una base de datos. Cada fila de la tabla se añade con un array de Objetos.
Para facilitar el manejo podemos usar un modelo ''DefaultTableModel'' y añadirselo al componente JTable.
https://docs.oracle.com/javase/tutorial/uiswing/components/table.html
==== JTextPane, JEditorPane ====
Se usan para mostrar texto con formato.
https://docs.oracle.com/javase/tutorial/uiswing/components/editorpane.html
----
(c) {{date> %Y}} Fernando Valdeón