View
187
Download
0
Category
Tags:
Preview:
Citation preview
Capitulo 5. SWING 5.1. Introducción 5.2. Contenedores de Alto Nivel 5.2.1. JWindow 5.2.2. JFrame 5.2.3. JDialog 5.3. Contenedores Intermedios 5.3.1. JPanel 5.3.2. JScrollPane 5.3.3. JSplitPane 5.4. Widgets 5.4.1. JLabel 5.4.2. JTextField 5.4.3. JTextArea 5.4.4. JButton 5.4.5. JCheckBox 5.4.6. RadioButton y ButtonGroup 5.4.7. JComboBox 5.4.8. JList 5.4.9. JTable 5.4.10. JTree 5.5. Layout 5.5.1. El layout null 5.5.2. FrowLayout 5.5.3. BoxLayout 5.5.4. GridLayout 5.5.5. BorderLayout 5.5.6. GridBagLayout 5.5.7. CardLayout 5.5.8. SpringLayout 5.6. Bean y Clases serializables 5.7. Look and Fiel 5.8. Archivos de Properties 5.9. Tablas y Modelos 5.10. Barras de Menú y Menús Contextuales 5.11. Drag-and-drop 5.12. DefaultTableCellRenderer y DefaultCellEditor 5.13. Ejemplos 5.14. Evaluacion
Ing. Elkin Doney Suárez Gómez MBA
Capitulo 5. SWING
5. 1. Introducción La mayor parte de las aplicaciones que se utilizan hoy en dia incluyen interfaces de
usuario mas sofisticadas que las de las apliaciones que se ejecutan modo consola.
Java incluye, como parte de su biblioteca de clases estándar, un conjunto de
componentes para crear interfaces graficas de usuario. Los componentes que se
utilizan en Java para crear interfaces graficas de usuario se agrupan en dos paquetes
AWT y SWING.
Los componentes AWT dependen de las facilidades graficas ofrecidas por cada
sistema operativo. Los programas escritos con AWT tendrá un “look and fiel” distinto
en Windows y en UNIX. SWING es 100% Java y por tanto completamente
independiente de la plataforma, los componentes graficos se pintan en tiempo de
ejecución por lo que las aplicaciones SWING suelen ser algo mas lentas que las AWT.
Cuando se creo SWING se hizo con el objetivo de evitar tener que usar los
componentes gráficos nativos de cada sistema operativo, y crear una interfaz que
fuera la misma en cualquier sistema operativo. Además el tener que usar los
componentes nativos generaba problemas ya que no se sabe como se comporta la
aplicación según el sistema operativo en el que fuese lanzado, al estar SWING
enteramente desarrollado en Java aumenta su portabilidad asegurando un
comportamiento idéntico en diferentes plataformas.
5.2. Contenedores de Alto Nivel
Un componente es un objeto que tiene una representación gráfica y que puede ser
mostrado por pantalla y que puede ser utilizado por el usuario
Los contenedores son componentes que pueden incluir a otros componentes. Utilizan
como base la clase java.awt.Component que está definida como abstracta.
Métodos de Información de la clase Component.
o String getName(). Obtiene el nombre del componente.
o void setName(String nombre). cambia el nombre del componente.
o Container getParent(). Devuelve el contenedor que sostiene a este
componente.
Métodos de apariencia y posición de la clase Component
o void setVisible(boolean b). Muestra u oculta el componente según el
valor del argumento sea true o false.
o Color getForeground(). Devuelve el color de frente.
o void setForeGround(Color color). Cambia el color frontal.
o Color getBackground(). Devuelve el color de fondo
o void setBackground(Color color). Cambia el color de fondo
o Point getLocation(). Devuelve la posición del componente en forma de
objeto Point.
o void setLocation(int x, int y). Coloca el componente en la posición x, y.
o void setLocation(Point p). Coloca el componente en la posición marcada
por las coordenadas del punto p.
o Dimension getSize(). Devuelve el tamaño del componente en un objeto
de tipo java.awt.Dimension.
o void setSize(Dimension d) o void setSize(int ancho, int alto). Cambia las
dimensiones del objeto en base a un objeto Dimension o indicando la
anchura y la altura con dos enteros.
o void setBounds(int x, int y, int ancho, int alto). Determina la posición de
la ventana (en la coordenada x, y) así como su tamaño con los
parámetros ancho y alto
o void setPreferredSize(Dimension d). Cambia el tamaño preferido del
componente. Este tamaño es el que el componente realmente quiere
tener.
o Cursor getCursor(). Obtiene el cursor del componente en forma de
objeto java.awt.Cursor
o void setCursor(Cursor cursor). Cambia el cursor del componente por el
o especificado en el parámetro.
o void setFont(Font fuente). Permite especificar el tipo de letra de la
fuente del texto.
Los objetos java.awt.Point tienen como propiedades públicas las coordenadas x e y.
Se construyen indicando el valor de esas coordenadas y disponen de varios métodos
que permiten modificar el punto. Los objetos java.awt.Dimension tienen como
propiedades la propiedad width (anchura) y height (altura). Los objetos java.awt.Color
representan colores y algunos constructores son:
Color(int rojo, int verde, int azul). Construye un objeto color indicando los
niveles de rojo, verde y azul.
Color(int rgb). Crea un color usando un único entero que indica los niveles de
rojo, verde y azul. Se suele emplear con 6 dígitos en hexadecimal. Ejemplo:
0xFFCC33.
Color(int rojo, int verde, int azul, int alfa). Construye un objeto color indicando
los niveles de rojo, verde y azul, y un valor de 0 a 255 indicando el valor alfa
(alfa indica la transparencia).
Además existen constantes de colores ya fabricados: Color.RED, Color.YELLOW,
Color.GREEN, Color.BLUE, Color.PINK, Color.GRAY, Color.CYAN,
Color.DARK_GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.PINK y
Color.WHITE.
Finalmente java.awt.Cursor es una clase que representa cursores y que se crea
indicando un número que se puede reemplazar por una serie de constantes estáticas
de la propia clase Cursor, que representan cursores. Las constantes son:
Cursor.HAND_CURSOR, Cursor.WAIT_CURSOR, Cursor.CROSSHAIR_CURSOR,
Cursor.TEXT_CURSOR, Cursor.DEFAULT_CURSOR y otros.
Métodos de dibujo de la clase Component
o void paint(Graphics p). Pinta el componente y sus subcomponentes.
Delega sus funciones en los tres métodos siguientes
o void paintComponents(Graphics p). Llama a los métodos de pintura de
todos los componentes de la ventana.
o void update(Graphics g). Llama a paint.
Activar y Desactivar componentes de la clase Component
o void setEnabled(boolean activar). Si el argumento es true se habilita el
componente, si no, se deshabilita.
Para que un componente sea al que van dirigidas las pulsaciones de las teclas o,
dicho de otra forma, el que recibe la interacción del usuario, debe poseer el enfoque
(focus). En muchos casos, el enfoque salta de un control al siguiente pulsando la tecla
tabulador. Varios métodos se encargan de controlar ese salto:
void requestFocus(). Pide el foco para el componente. Será posible, si este es
visible, activado y enfocable focusable. El contenedor del foco también poseerá
el foco.
boolean requestFocusInWindow(). Pide el foco para el componente si la
ventana contenedora poseía el foco. Devuelve true si el foco se puede dar sin
problemas. Aunque sólo el evento FOCUS_GAINED es el encargado de indicar
que el foco ha sido pasado. Actualmente, debido a que el método anterior es
dependiente de la plataforma, se recomienda este método siempre que sea
posible.
void transferFocus(). Hace que el siguiente componente en la lista de
tabulaciones, obtenga el foco.
void transferFocusBackward(). El foco pasa al anterior componente en la lista
de tabulaciones.
Estos métodos de la clase Container permiten obtener información sobre componentes
de un contenedor:
Component[] getComponents(). Devuelve un array de componentes con todos
los componentes correspondientes al contenedor actual
void list(PrintWriter out). Escribe en el objeto PrintWriter indicado, la lista de
componentes.
Component getComponentAt(int x, int y). Indica qué componente se encuentra
en esas coordenadas (calculadas dentro del sistema de coordenadas del
contenedor).
5.2.1. JWindow Este objeto deriva de la clase java.awt.Window que a su vez deriva de
java.awt.Container. Se trata de un objeto que representa un marco de ventana simple,
sin borde, ni ningún elemento. Sin embargo son contenedores a los que se les puede
añadir información. Estos componentes suelen estar dentro de una ventana de tipo
JFrame.
Constructores:
o JWindow(). Crea un marco de ventana típico e independiente.
o JWindow(Frame padre). Crea un marco de ventana dentro de la
ventana tipo Frame indicada.
o JWindow(Window padre). Crea un marco de ventana dentro de la
ventana indicada.
o JWindow(GraphicsConfiguration gc). Crea una nueva ventana usando la
configuración gráfica indicada
o JWindow(Window padre,GraphicsConfiguration gc). Crea una ventana
dentro de la padre con la configuración de gráficos indicada
5.2.2. JFrame
Objeto que representa una ventana típica con bordes, botones: cerrar, restaurar y
minimizar. Toda aplicación debe tener un único JFrame principal.
La manera más adecuada de crear un JFrame es:
Todos las clases que vayamos a crear deben extender de un componente SWING, es
este caso “MiFrame” hereda de un JFrame. Los objetos JFrame derivan de la clase
Frame que, a su vez deriva, también de la clase Window. Los objetos JFrame son
ventanas completas. Eclipse genera la siguiente estructura de código.
import javax.swing.JFrame;
public class MiFrame extends JFrame {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
Constructores
o JFrame(). Crea una ventana con la configuración normal.
o JFrame(GraphicsConfiguration gc). Crea una nueva ventana usando la
configuración gráfica indicada
o JFrame(String titulo). Crea una ventana con el título indicado.
o JFrame(String titulo, GraphicsConfiguration gc). Crea una ventana con
el título y la configuración gráfica indicada.
Métodos
o void setDefaultCloseOperation(int modo) Indica el modo de cerrar la
ventana, en sustitución del entero se puede utilizar los siguientes
valores:
JFrame.EXIT_ON_CLOSE. Al cerrar la ventana, se acaba el
programa.
JFrame.DO_NOTHING_ON_CLOSE. No se hace nada al cerrar
la ventana
JFrame.HIDE_ON_CLOSE. Esconde la ventana al cerrarla.
JFrame.DISPOSE_ON_CLOSE. Esconde la ventana y se
deshace de ella. El programa acaba cuando todas las ventanas
han sido cerradas con esta opción.
void setResizable(boolean b). Con true la ventana es cambiable
de tamaño, en false la ventana tiene tamaño fijo.
void setTitle(String t). Cambia el título de la ventana
void pack() Ajusta la ventana a tamaño suficiente para ajustar
sus contenidos
void setState(int estado) Coloca la ventana en uno de estos dos
estados:
Frame.NORMAL
Frame.ICONOFIED.
setExtendedState(int estado). Idéntica a la anterior pero añade
tres estados:
JFrame.MAXIMIZED_HOR. Maximizada horizontal
JFrame.MAXIMIZED_VER. Maximizada vertical
JFrame.MAXIMIZED_BOTH. Maximizada completa
int getState() Indica el estado de la ventana.
int getExtendedState() Indica el estado de la ventana.
o setVisible(boolean b). True para mostrar ventana, false la ventana se
oculta.
o void toBack(). Coloca la ventana al fondo, el resto de ventanas
aparecen por delante
o void toFront(). Envía la ventana al frente (además le dará el foco).
Se le implemento a la clase “MiFrame” el constructor por defecto MiFrame, y la palabra
super llama al constructor del padre “JFrame” el cual crea una ventana con
configuración normal. El método inicializar permite el uso se ciertos métodos del
JFrame vistos anteriormente y el método showCentered permite centrar la ventana en
la pantalla del PC.
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Toolkit;
import javax.swing.JFrame;
public class MiFrame extends JFrame {
public MiFrame() {
super();
inicializar();
}
public void inicializar(){
Dimension screenSize = null;
try {
this.setTitle("Mi primer frame");
this.setExtendedState(Frame.MAXIMIZED_BOTH);
this.setResizable(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.getExtendedState();
this.getState();
screenSize = Toolkit.getDefaultToolkit().getScreenSize();
if (screenSize.width < 1024){
setSize(800, 600);
}
else{
setSize(1024, 768);
}
} catch (java.lang.Throwable ivjExc){}
}
public void showCentered(int xOffset, int yOffset) {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = getSize();
if (frameSize.height > screenSize.height){
frameSize.height = screenSize.height;
}
if (frameSize.width > screenSize.width){
frameSize.width = screenSize.width;
}
int nXPos = (screenSize.width - frameSize.width) / 2 + xOffset;
int nYPos = (screenSize.height - frameSize.height) / 2 + yOffset;
setLocation(nXPos, nYPos);
setVisible(true);
}
public static void main(String[] args) {
new MiFrame().showCentered(0, 0);
}
}
5.2.3. JDialog Clase que genera un cuadro de diálogo. JDialog deriva de la clase AWT Dialog que es
subclase de Window. Representa un cuadro de diálogo que es una ventana
especializada para realizar operaciones complejas.
La forma más adecuada de crear un JDialog se muestra a continuación:
La clase “MiDialog” hereda de un JDialog, el IDE Eclipse genera la siguiente estructura
de código.
public class MiDialog extends JDialog {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
Constructores
o JDialog(). Crea una ventana con la configuración normal.
o JDialog(Frame propietaria). Crea un nuevo cuadro de diálogo, indicando
como padre la ventana seleccionada
o JDialog(Frame propietaria, boolean modal). Crea un nuevo cuadro de
diálogo, indicando como padre la ventana seleccionada. Poniendo a
true el segundo parámetro, el cuadro de diálogo pasa a ser modal. Una
ventana modal obliga al usuario a contestar al cuadro antes de que
pueda continuar trabajando.
o JDialog(Frame propietaria, String título). Crea un cuadro de diálogo
perteneciente a la ventana indicada y poniendo el título deseado.
o JDialog(Frame propietaria, String título, boolean modal). Crea un cuadro
de diálogo perteneciente a la ventana indicada, poniendo el título
deseado e indicando si se desea el cuadro en forma modal.
o JDialog(Frame propietaria, String título, boolean modal,
GraphicsConfiguration gc). Lo mismo, pero además indicando una
posible configuración gráfica.
Es recomendable definir varios constructores para la clase “MiDialog”, ya que este
puede tener como padre una clase que herede de un JFrame o un JDialog o ninguna
ventana como padre.
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JDialog;
public class MiDialog extends JDialog {
public MiDialog(Frame frame) {
super(frame,true);
inicializar();
}
public MiDialog(Dialog dialog) {
super(dialog,true);
inicializar();
}
public MiDialog() {
this((Frame) null);
}
private void inicializar(){
this.setSize(new Dimension(450, 270));
this.setResizable(false);
this.setTitle("Mi primer dialog");
this.setLocationRelativeTo(null);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e){
dispose();
}
});
}
public static void main(String[] args) {
new MiDialog().setVisible(true);
}
}
5.3. Contenedores Intermedios La mayoría de los componentes Swing están implementados como subclases de la
clase JComponent, que desciende de la clase Container y esta desciende de
Component. Algunas de las funcionalidades de la clase JComponent son:
Bordes. Usando el método setBorder, podemos especificar el borde que
muestra un componente alrededor de sus lados. Podemos especificar que un
componente tenga un espacio extra alrededor de sus lados usando un ejemplar
de EmptyBorder.
Doble buffer. El doble buffer puede mejorar la apariencia de un componente
que cambie frecuentemente. Ahora no tenemos que escribir nosotros el código
del doble buffer -- Swing nos los proporciona. Por defecto, los componentes
Swing usan el doble Buffer. Llamando al método setDoubleBuffered(false)
sobre un componente se desactiva el doble buffer.
Tool tips. Especificando un String con el método setToolTipText, podemos
proporcionarle ayuda al usuario de un componente. Cuando el cursor se para
sobre el componente, el String especificado se muestra en una pequeña
ventana que aparece cerca del componente.
Navegación con Teclado. Usando el método registerKeyboardAction, podemos
permitir que el usuario use el teclado en vez del ratón para moverse por el GUI.
void paintComponent(Graphics p). Pinta sólo este componente. Este es el
método recomendado en Swing para dibujar en un componente.
void paintChildren(Graphics p). Pinta los componentes hijo de este
componente.
void paintBorder(Graphics p). Pinta el borde del componente protected
Graphics.
getComponentGraphics(Graphics g). Obtiene el objeto gráfico utilizado para
dibujar el componente. El argumento es el objeto gráfico original. El otro es el
tratado por el componente.
void setNextFocusableComponent(Component c). Hace que el componente c
sea el siguiente en la lista de tabulaciones.
Component getNextFocusableComponent(). Obtiene el siguiente componente
de la lista de tabulaciones.
Los contenedores intermedios son aquellos que se colocan en el contenedor de alto
nivel y que su vez pueden contener otros componentes o Widgets. A continuación se
presentan los contenedores intermedios.
5.3.1. JPanel
Un JPanel permite agrupar a otros componentes, para el siguiente ejemplo se utilizo el
layout “BorderLayout” de la clase “MiDialog”. Este layout es el que usa por defecto el
JDialog.
import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JDialog;
import javax.swing.JPanel;
public class MiDialog extends JDialog {
private JPanel ejemploPanel;
public MiDialog(Frame frame) {
super(frame,true);
inicializar();
}
public MiDialog(Dialog dialog) {
super(dialog,true);
inicializar();
}
public MiDialog() {
this((Frame) null);
}
private void inicializar(){
this.setSize(new Dimension(450, 270));
this.setResizable(false);
this.setTitle("Mi primer dialog");
this.setLocationRelativeTo(null);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e){
dispose();
}
});
getContentPane().add(getEjemploPanel(), BorderLayout.CENTER);
}
protected JPanel getEjemploPanel() {
if (ejemploPanel == null) {
ejemploPanel = new JPanel();
}
return ejemploPanel;
}
public static void main(String[] args) {
new MiDialog().setVisible(true);
}
}
Cuando se diseñan ventanas, se usa el editor de diseño de WindowBuilder Pro, este
editor se puede configurar de tal manera que genera un método ya sea protegido o
privado para el componente que se desea agregar en el contenedor de alto nivel:
JFrame o JDialog. En el ejemplo anterior se crea una variable de tipo JPanel llamada
“ejemploPanel” esta variable es privada. Se mantiene el concepto de que todas las
variables de clase deben ser privadas. Esta variable la coloca el editor en el código
una vez estemos agregando componentes e inmediatamente crea el siguiente método:
protected JPanel getEjemploPanel() {
if (ejemploPanel == null) {
ejemploPanel = new JPanel();
}
return ejemploPanel;
}
La estructura de este método permite que el componente solo se cree una sola vez, es
recomendable acceder al componente por la llamada del método. getEjemploPanel()
ya sea dentro de la clase o fuera de la clase.
Dentro de este método podemos agregar propiedades adicionales para el
componente, por ejemplo color, tamaño, border etc.
En el constructor de la clase el editor genero la siguiente línea de código:
getContentPane().add(getEjemploPanel(), BorderLayout.CENTER);
Esa línea de código permite agregar el componente “EjemploPanel” en el centro del
contenedor de alto nivel en este caso la clase “MiDialog”.
Ahora si la idea es tener un contenedor intermedio en la parte norte, centro y sur del
dialogo. La estructura de diseño y código es:
import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JDialog;
import javax.swing.JPanel;
public class MiDialog extends JDialog {
private JPanel surPanel;
private JPanel nortePanel;
private JPanel centroPanel;
public MiDialog(Frame frame) {
super(frame,true);
inicializar();
}
public MiDialog(Dialog dialog) {
super(dialog,true);
inicializar();
}
public MiDialog() {
this((Frame) null);
}
private void inicializar(){
this.setSize(new Dimension(450, 270));
this.setResizable(false);
this.setTitle("Mi primer dialog");
this.setLocationRelativeTo(null);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e){
dispose();
}
});
getContentPane().add(getCentroPanel(), BorderLayout.CENTER);
getContentPane().add(getNortePanel(), BorderLayout.NORTH);
getContentPane().add(getSurPanel(), BorderLayout.SOUTH);
}
protected JPanel getCentroPanel() {
if (centroPanel == null) {
centroPanel = new JPanel();
}
return centroPanel;
}
protected JPanel getNortePanel() {
if (nortePanel == null) {
nortePanel = new JPanel();
nortePanel.setPreferredSize(new Dimension(0, 40));
}
return nortePanel;
}
protected JPanel getSurPanel() {
if (surPanel == null) {
surPanel = new JPanel();
surPanel.setPreferredSize(new Dimension(0, 40));
}
return surPanel;
}
public static void main(String[] args) {
new MiDialog().setVisible(true);
}
}
5.3.2. JScrollPane
Proporciona una vista desplazable de un componente ligero. Cuando el estado de la
pantalla real está limitado, se utiliza un ScrollPane para mostrar un componente que
es grande o cuyo tamaño puede cambiar dinámicamente. Ejemplo: JTable, JTree y
JTextArea.
Todo componente JPanel utiliza el layout “FrowLayout”, como layout por defecto. Para
agregar un JScrollPane en la región central del panel “centroPanel” se debe modificar
la propiedad layout del panel por “BorderLayout”.
La estructura de diseño y código se muestra a continuación:
private JScrollPane centroScrollPane;
protected JPanel getCentroPanel() {
if (centroPanel == null) {
centroPanel = new JPanel();
centroPanel.setLayout(new BorderLayout());
centroPanel.add(getCentroScrollPane(), BorderLayout.CENTER);
}
return centroPanel;
}
protected JScrollPane getCentroScrollPane() {
if (centroScrollPane == null) {
centroScrollPane = new JScrollPane();
}
return centroScrollPane;
}
Lo nuevo que el editor de diseño genera para la clase “MiDialog” es:
Una variable privada llamada “centroScrollPane” de tipo JScrollPane
centroPanel.setLayout(new BorderLayout()); Para el panel que va a contener el JScrollPane.
centroPanel.add(getCentroScrollPane(), BorderLayout.CENTER); agregar el
JScrollPanel al panel.
El método protegido para el componente JScrollPane.
5.3.3. JSplitPane
Contiene dos componentes de peso ligero, separados por un divisor. Arrastrando el
divisor, el usuario puede especificar qué cantidad de área pertenece a cada
componente. Un SplitPane se utiliza cuando dos componentes contienen información
relacionada y queremos que el usuario pueda cambiar el tamaño de los componentes
en relación a uno o a otro.
5.4. Widgets Son una representación visible de un componente que puede ser manipulada por el
usuario. Botones, campos de texto y barras de desplazamiento.
5.4.1. JLabel
La clase JLabel se utiliza para crear etiquetas de texto.
El siguiente ejemplo agregar una JLabel al panel del norte de la clase “MiDialog”.
private JLabel ejemploLabel;
protected JPanel getNortePanel() {
if (nortePanel == null) {
nortePanel = new JPanel();
nortePanel.setPreferredSize(new Dimension(0, 40));
nortePanel.add(getEjemploLabel());
}
return nortePanel;
}
protected JLabel getEjemploLabel() {
if (ejemploLabel == null) {
ejemploLabel = new JLabel();
ejemploLabel.setText("Ejemplo de una JLabel");
}
return ejemploLabel;
}
5.4.2. JTextField
Los objetos de esta clase se utilizan para el usuario pueda introducir datos a la
aplicación.
El siguiente ejemplo agrega una JLabel y un JTextField al panel sur del de la clase
“MiDialog”. Se modifica la propiedad layout del panel y se coloca null para agregar los
objetos más fácil.
private JTextField ejemploTextField;
private JLabel buscarLabel;
protected JPanel getSurPanel() {
if (surPanel == null) {
surPanel = new JPanel();
surPanel.setLayout(null);
surPanel.setPreferredSize(new Dimension(0, 40));
surPanel.add(getBuscarLabel());
surPanel.add(getEjemploTextField());
}
return surPanel;
}
protected JLabel getBuscarLabel() {
if (buscarLabel == null) {
buscarLabel = new JLabel();
buscarLabel.setText("Buscar");
buscarLabel.setBounds(294, 10, 50, 16);
}
return buscarLabel;
}
protected JTextField getEjemploTextField() {
if (ejemploTextField == null) {
ejemploTextField = new JTextField();
ejemploTextField.setBounds(350, 8, 87, 20);
}
return ejemploTextField;
}
5.4.3. JTextArea
Los objetos de esta clase se utilizan para introducir datos de tipo texto de gran
tamaño.
5.4.4. JButton
Un objeto de esta clase representa un botón. El siguiente ejemplo agrega un botón en
el panel sur de la clase “MiDialog”. Se agrega el evento addActionListener al botón.
Esta interfaz implementa el método actionPerformed que permite detectar los clics que
se hacen con el mouse sobre el botón.
private JButton ejemploButton;
protected JPanel getSurPanel() {
if (surPanel == null) {
surPanel = new JPanel();
surPanel.setLayout(null);
surPanel.setPreferredSize(new Dimension(0, 40));
surPanel.add(getBuscarLabel());
surPanel.add(getEjemploTextField());
surPanel.add(getEjemploButton());
}
return surPanel;
}
protected JButton getEjemploButton() {
if (ejemploButton == null) {
ejemploButton = new JButton();
ejemploButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
dispose();//metodo que cierra el dialogo
}
});
ejemploButton.setText("Cerrar");
ejemploButton.setBounds(10, 10, 80, 23);
}
return ejemploButton;
}
5.4.5. JCheckBox
Nos permite seleccionar varias opciones marcando el cuadrito que aparece a su
izquierda. El cuadrito pulsado equivale a un "sí" y sin pulsar a un "no" o, lo que es lo
mismo, a "true" o "false".
El siguiente ejemplo crea un JCheckBox en el panel sur de la clase “MiDialog”. Se
agrega el evento addActionListener al checkbox. Esta interfaz implementa el método
actionPerformed que permite detectar los clics que se hace con el mouse sobre el
JCheckbox. Este JCheckBox permite ocultar o mostrar la label y la caja de texto que
se muestra en la parte derecha del panel.
private JCheckBox ejemploCheckBox;
protected JPanel getSurPanel() {
if (surPanel == null) {
surPanel = new JPanel();
surPanel.setLayout(null);
surPanel.setPreferredSize(new Dimension(0, 40));
surPanel.add(getBuscarLabel());
surPanel.add(getEjemploTextField());
surPanel.add(getEjemploButton());
surPanel.add(getEjemploCheckBox());
}
return surPanel;
}
protected JCheckBox getEjemploCheckBox() {
if (ejemploCheckBox == null) {
ejemploCheckBox = new JCheckBox();
ejemploCheckBox.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
getEjemploTextField().setVisible(ejemploCheckBox.isSelected());
getBuscarLabel().setVisible(getEjemploTextField().isVisible());
}
});
ejemploCheckBox.setText("Mostrar búsqueda");
ejemploCheckBox.setBounds(119, 8, 153, 24);
ejemploCheckBox.setSelected(true);
}
return ejemploCheckBox;
}
5.4.6. JRadioButton y ButtonGroup
Permite al usuario seleccionar una única opción entre un grupo de elecciones. El
ButtonGroup agrupa los JRadioButtons de forma que solo pueda estar seleccionado
uno de ellos.
En el siguiente ejemplo se crea tres JRadioButton en el panel norte de la clase
“MiDialog”. Se modifica la propiedad layout del panel por null, para agregar más fácil
los componentes. Estos JRadioButton cambian el color del fondo del panel del sur por
medio de la propiedad setBackground.
private JRadioButton verdeRadioButton;
private JRadioButton azulRadioButton;
private JRadioButton blacoRadioButton;
protected JRadioButton getBlacoRadioButton() {
if (blacoRadioButton == null) {
blacoRadioButton = new JRadioButton();
blacoRadioButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
getSurPanel().setBackground(Color.WHITE);
}
});
blacoRadioButton.setText("Blanco");
blacoRadioButton.setBounds(0, 25, 72, 24);
getAgruparButtonGroup().add(blacoRadioButton);
}
return blacoRadioButton;
}
protected JRadioButton getAzulRadioButton() {
if (azulRadioButton == null) {
azulRadioButton = new JRadioButton();
azulRadioButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
getSurPanel().setBackground(Color.BLUE);
}
});
azulRadioButton.setText("Azul");
azulRadioButton.setBounds(72, 25, 66, 24);
getAgruparButtonGroup().add(azulRadioButton);
}
return azulRadioButton;
}
protected JRadioButton getVerdeRadioButton() {
if (verdeRadioButton == null) {
verdeRadioButton = new JRadioButton();
verdeRadioButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
getSurPanel().setBackground(Color.GREEN);
}
});
verdeRadioButton.setText("Verde");
verdeRadioButton.setBounds(135, 25, 129, 24);
getAgruparButtonGroup().add(verdeRadioButton);
}
return verdeRadioButton;
}
protected ButtonGroup getAgruparButtonGroup(){
if(agruparButtonGroup == null){
agruparButtonGroup = new ButtonGroup();
}
return agruparButtonGroup;
}
Se modifico la propiedad setOpaque se JCheckBox en false.
5.4.7. JComboBox
Sirve para mostrar una lista desplegable de elementos.
En el siguiente ejemplo se crea un JComboBox en el panel sur de la clase “MiDialog”.
Para llenar el JComboBox de elementos se utilizo un objeto de la clase
DefaultComboBoxModel, por lo general casi la mayoría de componentes de SWING se
basan en modelos.
private JComboBox ejemploComboBox;
protected JPanel getSurPanel() {
if (surPanel == null) {
surPanel = new JPanel();
surPanel.setLayout(null);
surPanel.setPreferredSize(new Dimension(0, 40));
surPanel.add(getBuscarLabel());
surPanel.add(getEjemploTextField());
surPanel.add(getEjemploButton());
surPanel.add(getEjemploCheckBox());
surPanel.add(getEjemploComboBox());
}
return surPanel;
}
protected JCheckBox getEjemploCheckBox() {
if (ejemploCheckBox == null) {
ejemploCheckBox = new JCheckBox();
ejemploCheckBox.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
getEjemploTextField().setVisible(ejemploCheckBox.isSelected());
getBuscarLabel().setVisible(getEjemploTextField().isVisible());
getEjemploComboBox().setVisible(getEjemploTextField().isVisible());
}
});
ejemploCheckBox.setText("Mostrar búsqueda");
ejemploCheckBox.setBounds(99, 6, 153, 24);
ejemploCheckBox.setSelected(true);
ejemploCheckBox.setOpaque(false);
}
return ejemploCheckBox;
}
protected JComboBox getEjemploComboBox() {
if (ejemploComboBox == null) {
ejemploComboBox = new JComboBox();
ejemploComboBox.setBounds(284, 8, 78, 20);
DefaultComboBoxModel modelo = new DefaultComboBoxModel();
modelo.addElement("");
modelo.addElement("Código");
modelo.addElement("Nombre");
modelo.addElement("Apellido");
ejemploComboBox.setModel(modelo);
}
return ejemploComboBox;
}
5.4.8. JList
Los objetos de esta clase sirven para mostrar una lista con elementos.
5.4.9. JTable
Objetos del tipo JTable sirven para mostrar información en forma tabular.
En el siguiente ejemplo se agregar una JTable a “centroScrollPane” de la clase
“MiDialog”.
private JTable ejemploTable;
private TableRowSorter<TableModel> modeloOrdenado;
protected JScrollPane getCentroScrollPane() {
if (centroScrollPane == null) {
centroScrollPane = new JScrollPane();
centroScrollPane.setViewportView(getEjemploTable());
}
return centroScrollPane;
}
protected JTable getEjemploTable() {
if (ejemploTable == null) {
final String [] nombreCol = {"Codigo","Nombre","Telefono","Barrio"} ;
Object [] [] datos = {
{"1", "Oscar Corredor", "6453720", "La cumbre"},
{"2", "Andrea Lizcano", "6879371", "La aurora"},
{"3", "Angel Lizcano", "6879379", "Provenza"},
{"4", "Carolina Gómez", "6879373", "Niza"},
{"5", "Catalina Rodriguez", "6879374", "Diamante I" }
};
ejemploTable = new JTable(datos, nombreCol);
modeloOrdenado = new TableRowSorter<TableModel>
(ejemploTable.getModel());
ejemploTable.setRowSorter(modeloOrdenado);
}
return ejemploTable;
Con pasarle al JTable una instancia de TableRowSorter, a partir de ese momento,
haciendo click en la cabecera de las columnas con el ratón, ordenaremos el JTable en
orden ascendente o descendente alternativamente según esa columna.
Para filtrar por los elementos del comboBox, sólo tenemos que pasarle a nuestro
TableRowSorter un RowFilter una columna concreta, por medio del método
setRowFilter(). Este RowFilter es el que dice si un valor de esa columna (y por tanto la
fila entera del JTable) pasa o no pasa el filtro. Si el valor de esa columna no pasa el
filtro, la fila entera no lo pasa y no será visible. Podemos hacer nuestros propios
RowFilter heredando de esta clase e implementando su método abstracto include(),
pero RowFilter tiene varios métodos estáticos que nos proporcionan los filtros
habituales.
protected JComboBox getEjemploComboBox() {
if (ejemploComboBox == null) {
ejemploComboBox = new JComboBox();
ejemploComboBox.setBounds(284, 8, 78, 20);
DefaultComboBoxModel modelo = new DefaultComboBoxModel();
modelo.addElement("");
modelo.addElement("Código");
modelo.addElement("Nombre");
modelo.addElement("Telefono");
ejemploComboBox.setModel(modelo);
}
return ejemploComboBox;
}
protected JTextField getEjemploTextField() {
if (ejemploTextField == null) {
ejemploTextField = new JTextField();
ejemploTextField.addKeyListener(new KeyAdapter() {
public void keyReleased(final KeyEvent e) {
if(getEjemploComboBox().getSelectedIndex() > 0){
modeloOrdenado.setRowFilter(
RowFilter.regexFilter(
ejemploTextField.getText(),
getEjemploComboBox().getSelectedIndex()-1)
);
}
}
});
ejemploTextField.setBounds(363, 8, 74, 20);
}
return ejemploTextField;
}
En este ejemplo, se uso un filtro regex, es decir, el dato pasa el filtro si cumple un
determinado patrón, que será muy simple: pasa el filtro si tiene un "A". Para obtener
dicho RowFilter, usamos el método RowFilter.regexFilter().
Como primer parámetro se pasa una expresión regular (regex) que tiene que cumplir
el dato para pasar el filtro, en nuestro caso el valor de la propiedad getText de la caja
te texto que es “A”. Como segundo parámetro se pasa un entero para identificar la
columna a la que se quiere aplicar el filtro.
getSelectedIndex, es una propiedad del JComboBox que permite saber que ítem de
los elementos del combo esta seleccionado, teniendo en cuenta que el combo tiene un
elemento vacio se le restara -1 al ítem seleccionado. En este caso se selecciono el
ítem Nombre equivalente a 1.
5.4.10. JTree
Objetos de este tipo sirven para mostrar la información en forma de árbol.
En el siguiente ejemplo se hace un cambio en el diseño que se viene trabajando hasta
el ahora, se agregar un JSplitPane en la región central de “centroPanel” de la clase
“MiDialog” y en la parte derecha del JSplitPane se coloca el “centroScrollPane” de la
tabla “ejemploTable” y el la parte izquierda se coloca un JScrollPane para el JTree.
También se aumenta el tamaño del dialogo: this.setSize(new Dimension(490,
370));
private JTree ejemploTree;
private JSplitPane ejemploSplitPane;
private JScrollPane arbolScrollPane;
protected JPanel getCentroPanel() {
if (centroPanel == null) {
centroPanel = new JPanel();
centroPanel.setLayout(new BorderLayout());
centroPanel.add(getEjemploSplitPane());
}
return centroPanel;
}
protected JSplitPane getEjemploSplitPane() {
if (ejemploSplitPane == null) {
ejemploSplitPane = new JSplitPane();
ejemploSplitPane.setDividerSize(3);
ejemploSplitPane.setDividerLocation(140);
ejemploSplitPane.setLeftComponent(getArbolScrollPane());
ejemploSplitPane.setRightComponent(getCentroScrollPane());
}
return ejemploSplitPane;
}
protected JScrollPane getArbolScrollPane() {
if (arbolScrollPane == null) {
arbolScrollPane = new JScrollPane();
arbolScrollPane.setViewportView(getEjemploTree());
}
return arbolScrollPane;
}
protected JTree getEjemploTree() {
if (ejemploTree == null) {
ejemploTree = new JTree();
}
return ejemploTree;
}
Una estructura de árbol sencilla se crea de la siguiente manera:
private DefaultMutableTreeNode asignar = null;
private DefaultMutableTreeNode contienente = null;
private DefaultMutableTreeNode pais = null;
protected JTree getEjemploTree() {
if (ejemploTree == null) {
asignar = new DefaultMutableTreeNode ("El Mundo") ;
contienente = new DefaultMutableTreeNode ("America") ;
asignar.add (contienente) ;
pais = new DefaultMutableTreeNode ("Colombia") ;
contienente.add(pais) ;
pais = new DefaultMutableTreeNode ("México") ;
contienente.add(pais) ;
contienente = new DefaultMutableTreeNode ("Europa") ;
asignar.add ( contienente ) ;
pais = new DefaultMutableTreeNode ("España") ;
contienente.add (pais) ;
pais = new DefaultMutableTreeNode ("Alemania") ;
contienente.add (pais) ;
pais = new DefaultMutableTreeNode ("Italia") ;
contienente.add(pais) ;
ejemploTree = new JTree(asignar);
}
return ejemploTree;
}
La clase completa de los ejercicios de los componentes básicos de SWING se muestra
continuación.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.ButtonGroup;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.RowFilter;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import javax.swing.tree.DefaultMutableTreeNode;
public class MiDialog extends JDialog {
private JTree ejemploTree;
private JSplitPane ejemploSplitPane;
private JScrollPane arbolScrollPane;
private JTable ejemploTable;
private JComboBox ejemploComboBox;
private JRadioButton verdeRadioButton;
private JRadioButton azulRadioButton;
private JRadioButton blacoRadioButton;
private JCheckBox ejemploCheckBox;
private JButton ejemploButton;
private JTextField ejemploTextField;
private JLabel buscarLabel;
private JLabel ejemploLabel;
private JScrollPane centroScrollPane;
private JPanel surPanel;
private JPanel nortePanel;
private JPanel centroPanel;
private ButtonGroup agruparButtonGroup;
private TableRowSorter<TableModel> modeloOrdenado = null;
private DefaultMutableTreeNode asignar = null;
private DefaultMutableTreeNode contienente = null ;
private DefaultMutableTreeNode pais = null;
public MiDialog(Frame frame) {
super(frame,true);
inicializar();
}
public MiDialog(Dialog dialog) {
super(dialog,true);
inicializar();
}
public MiDialog() {
this((Frame) null);
}
private void inicializar(){
this.setSize(new Dimension(490, 370));
this.setResizable(false);
this.setTitle("Mi primer dialog");
this.setLocationRelativeTo(null);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e){
dispose();
}
});
getContentPane().add(getCentroPanel(), BorderLayout.CENTER);
getContentPane().add(getNortePanel(), BorderLayout.NORTH);
getContentPane().add(getSurPanel(), BorderLayout.SOUTH);
}
protected JPanel getCentroPanel() {
if (centroPanel == null) {
centroPanel = new JPanel();
centroPanel.setLayout(new BorderLayout());
centroPanel.add(getEjemploSplitPane());
}
return centroPanel;
}
protected JPanel getNortePanel() {
if (nortePanel == null) {
nortePanel = new JPanel();
nortePanel.setLayout(null);
nortePanel.setPreferredSize(new Dimension(0, 50));
nortePanel.add(getEjemploLabel());
nortePanel.add(getBlacoRadioButton());
nortePanel.add(getAzulRadioButton());
nortePanel.add(getVerdeRadioButton());
}
return nortePanel;
}
protected JPanel getSurPanel() {
if (surPanel == null) {
surPanel = new JPanel();
surPanel.setLayout(null);
surPanel.setPreferredSize(new Dimension(0, 40));
surPanel.add(getBuscarLabel());
surPanel.add(getEjemploTextField());
surPanel.add(getEjemploButton());
surPanel.add(getEjemploCheckBox());
surPanel.add(getEjemploComboBox());
}
return surPanel;
}
public static void main(String[] args) {
new MiDialog().setVisible(true);
}
protected JScrollPane getCentroScrollPane() {
if (centroScrollPane == null) {
centroScrollPane = new JScrollPane();
centroScrollPane.setViewportView(getEjemploTable());
}
return centroScrollPane;
}
protected JLabel getEjemploLabel() {
if (ejemploLabel == null) {
ejemploLabel = new JLabel();
ejemploLabel.setBounds(158, 5, 127, 16);
ejemploLabel.setText("Ejemplo de una JLabel");
}
return ejemploLabel;
}
protected JLabel getBuscarLabel() {
if (buscarLabel == null) {
buscarLabel = new JLabel();
buscarLabel.setText("Buscar");
buscarLabel.setBounds(281, 12, 50, 16);
}
return buscarLabel;
}
protected JTextField getEjemploTextField() {
if (ejemploTextField == null) {
ejemploTextField = new JTextField();
ejemploTextField.addKeyListener(new KeyAdapter() {
public void keyReleased(final KeyEvent e) {
if(getEjemploComboBox().getSelectedIndex() > 0){
modeloOrdenado.setRowFilter(
RowFilter.regexFilter(
ejemploTextField.getText(),
getEjemploComboBox().getSelectedIndex()-1)
);
}
}
});
ejemploTextField.setBounds(407, 10, 74, 20);
}
return ejemploTextField;
}
protected JButton getEjemploButton() {
if (ejemploButton == null) {
ejemploButton = new JButton();
ejemploButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
dispose();//metodo que cierra el dialogo
}
});
ejemploButton.setText("Cerrar");
ejemploButton.setBounds(10, 10, 80, 23);
}
return ejemploButton;
}
protected JCheckBox getEjemploCheckBox() {
if (ejemploCheckBox == null) {
ejemploCheckBox = new JCheckBox();
ejemploCheckBox.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
getEjemploTextField().setVisible(ejemploCheckBox.isSelected());
getBuscarLabel().setVisible(getEjemploTextField().isVisible());
getEjemploComboBox().setVisible(getEjemploTextField().isVisible());
}
});
ejemploCheckBox.setText("Mostrar búsqueda");
ejemploCheckBox.setBounds(99, 6, 153, 24);
ejemploCheckBox.setSelected(true);
ejemploCheckBox.setOpaque(false);
}
return ejemploCheckBox;
}
protected JRadioButton getBlacoRadioButton() {
if (blacoRadioButton == null) {
blacoRadioButton = new JRadioButton();
blacoRadioButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
getSurPanel().setBackground(Color.WHITE);
}
});
blacoRadioButton.setText("Blanco");
blacoRadioButton.setBounds(0, 25, 72, 24);
getAgruparButtonGroup().add(blacoRadioButton);
}
return blacoRadioButton;
}
protected JRadioButton getAzulRadioButton() {
if (azulRadioButton == null) {
azulRadioButton = new JRadioButton();
azulRadioButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
getSurPanel().setBackground(Color.BLUE);
}
});
azulRadioButton.setText("Azul");
azulRadioButton.setBounds(72, 25, 66, 24);
getAgruparButtonGroup().add(azulRadioButton);
}
return azulRadioButton;
}
protected JRadioButton getVerdeRadioButton() {
if (verdeRadioButton == null) {
verdeRadioButton = new JRadioButton();
verdeRadioButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
getSurPanel().setBackground(Color.GREEN);
}
});
verdeRadioButton.setText("Verde");
verdeRadioButton.setBounds(135, 25, 129, 24);
getAgruparButtonGroup().add(verdeRadioButton);
}
return verdeRadioButton;
}
protected ButtonGroup getAgruparButtonGroup(){
if(agruparButtonGroup == null){
agruparButtonGroup = new ButtonGroup();
}
return agruparButtonGroup;
}
protected JComboBox getEjemploComboBox() {
if (ejemploComboBox == null) {
ejemploComboBox = new JComboBox();
ejemploComboBox.setBounds(328, 10, 78, 20);
DefaultComboBoxModel modelo = new DefaultComboBoxModel();
modelo.addElement("");
modelo.addElement("Código");
modelo.addElement("Nombre");
modelo.addElement("Telefono");
ejemploComboBox.setModel(modelo);
}
return ejemploComboBox;
}
protected JTable getEjemploTable() {
if (ejemploTable == null) {
final String [] nombreCol = {"Codigo","Nombre","Telefono","Barrio"} ;
Object [] [] datos = {
{"1", "Oscar Corredor", "6453720", "La cumbre"},
{"2", "Andrea Lizcano", "6879371", "La aurora"},
{"3", "Angel Lizcano", "6879379", "Provenza"},
{"4", "Carolina Gómez", "6879373", "Niza"},
{"5", "Catalina Rodriguez", "6879374", "Diamante I" }
};
ejemploTable = new JTable(datos, nombreCol);
modeloOrdenado = new TableRowSorter<TableModel>
(ejemploTable.getModel());
ejemploTable.setRowSorter(modeloOrdenado);
}
return ejemploTable;
}
protected JScrollPane getArbolScrollPane() {
if (arbolScrollPane == null) {
arbolScrollPane = new JScrollPane();
arbolScrollPane.setViewportView(getEjemploTree());
}
return arbolScrollPane;
}
protected JSplitPane getEjemploSplitPane() {
if (ejemploSplitPane == null) {
ejemploSplitPane = new JSplitPane();
ejemploSplitPane.setDividerSize(3);
ejemploSplitPane.setDividerLocation(140);
ejemploSplitPane.setLeftComponent(getArbolScrollPane());
ejemploSplitPane.setRightComponent(getCentroScrollPane());
}
return ejemploSplitPane;
}
protected JTree getEjemploTree() {
if (ejemploTree == null) {
asignar = new DefaultMutableTreeNode ("El Mundo") ;
contienente = new DefaultMutableTreeNode ("America") ;
asignar.add (contienente) ;
pais = new DefaultMutableTreeNode ("Colombia") ;
contienente.add(pais) ;
pais = new DefaultMutableTreeNode ("México") ;
contienente.add(pais) ;
contienente = new DefaultMutableTreeNode ("Europa") ;
asignar.add ( contienente ) ;
pais = new DefaultMutableTreeNode ("España") ;
contienente.add (pais) ;
pais = new DefaultMutableTreeNode ("Alemania") ;
contienente.add (pais) ;
pais = new DefaultMutableTreeNode ("Italia") ;
contienente.add(pais) ;
ejemploTree = new JTree(asignar);
}
return ejemploTree;
}
}
5.5. Layout
En Java, cuando hacemos ventanas, la clase que decide cómo se reparten los
botones (Y demás controles) dentro de la ventana se llama Layout. Esta clase es la
que decide en qué posición van los botones y demás componentes, si van alineados,
en forma de matriz, cuáles se hacen grandes al agrandar la ventana, etc. Otra cosa
importante que decide el Layout es qué tamaño es el ideal para la ventana en función
de los componentes que lleva dentro. Con un layout adecuado, el método pack() de la
ventana hará que coja el tamaño necesario para que se vea todo lo que tiene dentro.
Las ventanas vienen con un Layout por defecto. En Java hay varios layouts
disponibles y podemos cambiar el de por defecto por otro.
5.5.1. El Layout null
Uno de los Layouts más utilizados, desde código se da la poscicion y el tamaño que
ocupa el componente.
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class EjemploLayoutNullPanel extends JPanel {
private JButton okButton;
private JTextField nombreTextField;
private JTextField codigoTextField;
private JLabel nombreLabel;
private JLabel codigoLabel;
private JLabel ejemploLayoutNullLabel;
public EjemploLayoutNullPanel() {
super();
setLayout(null);
add(getEjemploLayoutNullLabel());
add(getCodigoLabel());
add(getNombreLabel());
add(getCodigoTextField());
add(getNombreTextField());
add(getOkButton());
}
protected JLabel getEjemploLayoutNullLabel() {
if (ejemploLayoutNullLabel == null) {
ejemploLayoutNullLabel = new JLabel();
ejemploLayoutNullLabel.setText("Ejemplo Layout Null");
ejemploLayoutNullLabel.setBounds(88, 10, 121, 16);
}
return ejemploLayoutNullLabel;
}
protected JLabel getCodigoLabel() {
if (codigoLabel == null) {
codigoLabel = new JLabel();
codigoLabel.setText("Código");
codigoLabel.setBounds(10, 46, 66, 16);
}
return codigoLabel;
}
protected JLabel getNombreLabel() {
if (nombreLabel == null) {
nombreLabel = new JLabel();
nombreLabel.setText("Nombre");
nombreLabel.setBounds(10, 77, 66, 16);
}
return nombreLabel;
}
protected JTextField getCodigoTextField() {
if (codigoTextField == null) {
codigoTextField = new JTextField();
codigoTextField.setBounds(83, 44, 87, 20);
}
return codigoTextField;
}
protected JTextField getNombreTextField() {
if (nombreTextField == null) {
nombreTextField = new JTextField();
nombreTextField.setBounds(83, 75, 201, 20);
}
return nombreTextField;
}
protected JButton getOkButton() {
if (okButton == null) {
okButton = new JButton();
okButton.setText("Ok");
okButton.setBounds(120, 118, 50, 20);
}
return okButton;
}
}
Se agrega el panel a un JFrame
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
public class EjemplosLayoutFrame extends JFrame {
private EjemploLayoutNullPanel layoutNullPanel;
public EjemplosLayoutFrame (){
this.setTitle("Ejemplo Layouts");
this.setLocationRelativeTo(null);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e){
dispose();
}
});
getContentPane().add(getLayoutNullPanel(), BorderLayout.CENTER);
this.setSize(new Dimension(293, 180));
}
protected EjemploLayoutNullPanel getLayoutNullPanel() {
if (layoutNullPanel == null) {
layoutNullPanel = new EjemploLayoutNullPanel();
}
return layoutNullPanel;
}
public static void main(String[] args) {
new EjemplosLayoutFrame().setVisible(true);
}
}
Esto, aunque sencillo, no es recomendable. Si estiramos la ventana los componentes
seguirán en su sitio, no se estirarán con la ventana. Si cambiamos de sistema
operativo, resolución de pantalla o fuente de letra, tenemos casi asegurado que no se
vean bien las cosas: etiquetas cortadas, letras que no caben, etc.
Además, al no haber layout, la ventana no tiene tamaño adecuado. Deberemos
dárselo nosotros con un ventana.setSize(...).
5.5.2. FlowLayout
El FlowLayout es bastante sencillo de usar. Nos coloca los componentes en fila. Hace
que todos quepan (si el tamaño de la ventana lo permite). Es adecuado para barras de
herramientas, filas de botones, etc. Este layout lo trae por defecto un JPanel.
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class EjemploFlowLayoutPanel extends JPanel {
private JLabel etiquetaLabel;
private JCheckBox opcionCheckBox;
private JTextField textoTextField;
private JButton botonButton;
public EjemploFlowLayoutPanel() {
super();
add(getBotonButton());
add(getTextoTextField());
add(getOpcionCheckBox());
add(getEtiquetaLabel());
}
protected JButton getBotonButton() {
if (botonButton == null) {
botonButton = new JButton();
botonButton.setText("Boton");
}
return botonButton;
}
protected JTextField getTextoTextField() {
if (textoTextField == null) {
textoTextField = new JTextField(10);
}
return textoTextField;
}
protected JCheckBox getOpcionCheckBox() {
if (opcionCheckBox == null) {
opcionCheckBox = new JCheckBox();
opcionCheckBox.setText("opcion");
}
return opcionCheckBox;
}
protected JLabel getEtiquetaLabel() {
if (etiquetaLabel == null) {
etiquetaLabel = new JLabel();
etiquetaLabel.setText("etiqueta");
}
return etiquetaLabel;
}
}
Se agrega el panel a un JFrame
import java.awt.BorderLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
public class EjemplosLayoutFrame extends JFrame {
private EjemploFlowLayoutPanel ejemploFlowLayoutPanel;
public EjemplosLayoutFrame(){
this.setTitle("Ejemplo Layouts");
this.setLocationRelativeTo(null);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e){
dispose();
}
});
getContentPane().add(getEjemploFlowLayoutPanel(), BorderLayout.CENTER);
this.pack();
}
protected EjemploFlowLayoutPanel getEjemploFlowLayoutPanel() {
if (ejemploFlowLayoutPanel == null) {
ejemploFlowLayoutPanel = new EjemploFlowLayoutPanel();
}
return ejemploFlowLayoutPanel;
}
public static void main(String[] args) {
new EjemplosLayoutFrame().setVisible(true);
}
}
5.5.3. BoxLayout
Es como un FlowLayout, pero mucho más completo. Permite colocar los elementos en
horizontal o vertical.
import java.awt.Component;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class EjemploBoxLayout extends JPanel {
private JLabel ejemploLabel;
private JButton ejemploButton;
public EjemploBoxLayout() {
super();
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
add(getEjemploButton());
add(getEjemploLabel());
}
protected JButton getEjemploButton() {
if (ejemploButton == null) {
ejemploButton = new JButton();
ejemploButton.setText("Ejemplo");
ejemploButton.setAlignmentX(Component.CENTER_ALIGNMENT);
}
return ejemploButton;
}
protected JLabel getEjemploLabel() {
if (ejemploLabel == null) {
ejemploLabel = new JLabel();
ejemploLabel.setText("Ejemplo");
ejemploLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
}
return ejemploLabel;
}
}
Se agrega el panel a un JFrame
Lo de BoxLayout.Y_AXIS es para que coloque los componentes en vertical, de arriba
abajo con BoxLayout.X_AXIS los coloca igual que un FlowLayout, de izquierda a
derecha.
También hay BoxLayout.LINE_AXIS e BoxLayout.PAGE_AXIS, pero el
comportamiento por defecto es igual. El comportamiento es distinto si al contenedor le
cambiamos el setComponentOrientation(), en cuyo caso podemos conseguir que los
componentes vayan de derecha a izquierda según los vamos añadiendo o de abajo a
arriba. Para que los componentes salgan centrados (la etiqueta y el botón) hay que
llamar al método AlignmentX(Component.CENTER_ALIGNMENT).
5.5.4. GridLayout
Este layout pone los componentes en forma de matriz (cuadrícula), estirándolos para
que tengan todos los mismos tamaños. El GridLayout es adecuado para hacer
tableros, calculadoras en que todos los botones son iguales, etc.
import java.awt.GridLayout;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class EjemploGridLayout extends JPanel {
private JTextField[][] textField;
private static final int COLUMNAS = 10;
private static final int FILAS = 5;
public EjemploGridLayout() {
super();
setLayout(new GridLayout(FILAS, COLUMNAS));
textField = new JTextField [FILAS][COLUMNAS];
for (int i=0;i<FILAS;i++){
for (int j=0;j<COLUMNAS;j++){
textField[i][j] = new JTextField(4);
add(textField[i][j]);
}
}
}
}
Se agrega el panel a un JFrame
import java.awt.BorderLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import aplicacion.EjemploGridLayout;
public class EjemplosLayoutFrame extends JFrame {
private EjemploGridLayout ejemploGridLayout;
public EjemplosLayoutFrame (){
this.setTitle("Ejemplo Layouts");
this.setLocationRelativeTo(null);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e){
dispose();
}
});
getContentPane().add(getEjemploGridLayout(), BorderLayout.CENTER);
this.pack();
}
protected EjemploGridLayout getEjemploGridLayout() {
if (ejemploGridLayout == null) {
ejemploGridLayout = new EjemploGridLayout();
}
return ejemploGridLayout;
}
public static void main(String[] args) {
new EjemplosLayoutFrame().setVisible(true);
}
}
5.5.5. BorderLayout
El BorderLayout divide la ventana en 5 partes: centro, arriba, abajo, derecha e
izquierda. Hará que los componentes que pongamos arriba y abajo ocupen el alto que
necesiten, pero los estirará horizontalmente hasta ocupar toda la ventana. Los
componentes de derecha e izquierda ocuparán el ancho que necesiten, pero se les
estirará en vertical hasta ocupar toda la ventana. El componente central se estirará en
ambos sentidos hasta ocupar toda la ventana. El BorderLayout es adecuado para
ventanas en las que hay un componente central importante (una tabla, una lista, etc) y
tiene menús o barras de herramientas situados arriba, abajo, a la derecha o a la
izquierda. Este es el layout por defecto para los JFrame y JDialog.
5.5.6. GridBagLayout
El GridBagLayout es de los layouts más versátiles y complejos de usar. Es como el
GridLayout, pone los componentes en forma de matriz (cuadrícula), pero permite que
las celdas y los componentes en ellas tengan tamaños variados.
Es posible hacer que un componente ocupe varias celdas
Un componente puede estirarse o no con su celda
Si no se estira, puede quedar en el centro de la celda o pegarse a sus bordes o
esquinas.
Las columnas pueden ensancharse o no al estirar la ventana y la proporición
podemos decidirla
Lo mismo con la filas.
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
public class EjemploGridBagLayout extends JPanel {
private JButton button1;
private JButton button2;
private JButton button3;
private JButton button4;
private JButton button5;
private JButton button6;
private JButton button7;
private JButton button8;
private JButton button9;
public EjemploGridBagLayout() {
super();
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints gbc = new GridBagConstraints();
setLayout(gridbag);
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1.0;
gridbag.setConstraints(getButton1(),gbc );
add(getButton1());
gridbag.setConstraints(getButton2(),gbc );
add(getButton2());
gridbag.setConstraints(getButton3(),gbc );
add(getButton3());
gbc.gridwidth = GridBagConstraints.REMAINDER;
gridbag.setConstraints(getButton4(),gbc );
add(getButton4());
gbc.weightx = 0.0;
gridbag.setConstraints(getButton4(),gbc );
add(getButton4());
gbc.gridwidth = GridBagConstraints.RELATIVE;
gridbag.setConstraints(getButton5(),gbc);
add(getButton5());
gbc.gridwidth = GridBagConstraints.REMAINDER;
gridbag.setConstraints(getButton6(),gbc );
add(getButton6());
gbc.gridwidth = 1;
gbc.gridheight = 2;
gbc.weighty = 1.0;
gridbag.setConstraints(getButton7(),gbc );
add(getButton7());
gbc.weighty = 0.0;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridheight = 1;
gridbag.setConstraints(getButton8(),gbc );
add(getButton8());
gridbag.setConstraints(getButton9(),gbc );
add(getButton9());
}
protected JButton getButton1(){
if(button1 == null){
button1 = new JButton();
button1.setText("Botón 1");
}
return button1;
}
protected JButton getButton2(){
if(button2 == null){
button2 = new JButton();
button2.setText("Botón 2");
}
return button2;
}
protected JButton getButton3(){
if(button3 == null){
button3 = new JButton();
button3.setText("Botón 3");
}
return button3;
}
protected JButton getButton4(){
if(button4 == null){
button4 = new JButton();
button4.setText("Botón 4");
}
return button4;
}
protected JButton getButton5(){
if(button5 == null){
button5 = new JButton();
button5.setText("Botón 5");
}
return button5;
}
protected JButton getButton6(){
if(button6 == null){
button6 = new JButton();
button6.setText("Botón 6");
}
return button6;
}
protected JButton getButton7(){
if(button7 == null){
button7 = new JButton();
button7.setText("Botón 7");
}
return button7;
}
protected JButton getButton8(){
if(button8 == null){
button8 = new JButton();
button8.setText("Botón 8");
}
return button8;
}
protected JButton getButton9(){
if(button9 == null){
button9 = new JButton();
button9.setText("Botón 9");
}
return button9;
}
}
Se agrega el panel a un JFrame
import java.awt.BorderLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
public class EjemplosLayoutFrame extends JFrame {
private EjemploGridBagLayout ejemploGridBagLayout;
public EjemplosLayoutFrame (){
this.setTitle("Ejemplo Layouts");
this.setLocationRelativeTo(null);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e){
dispose();
}
});
getContentPane().add(getEjemploGridBagLayout(), BorderLayout.CENTER);
this.pack();
}
protected EjemploGridBagLayout getEjemploGridBagLayout() {
if (ejemploGridBagLayout == null) {
ejemploGridBagLayout = new EjemploGridBagLayout();
}
return ejemploGridBagLayout;
}
public static void main(String[] args) {
new EjemplosLayoutFrame().setVisible(true);
}
}
5.5.7. CardLayout
El CardLayout hace que los componentes recibidos ocupen el máximo espacio
posible, superponiendo unos a otros. Sólo es visible uno de los componentes, los otros
quedan detrás. Tiene métodos para indicar cual de los componentes es el que debe
quedar encima y verse.
El CardLayout es el que utiliza el JTabbedPane (el de las pestañas) de forma que en
función de la pestaña que pinchemos, se ve uno u otro.
5.5.8. SpringLayout
Se añaden los componentes y para cada uno de ellos tenemos que decir qué distancia
en pixel queremos que tenga cada uno de sus bordes respecto al borde del otro
componente.
5.6. Bean y Clases serializables
Un Bean es solo una clase serializable hecha en Java como cualquier otra, pero debe
seguir algunas reglas estandares para que se considere como Bean, por ejemplo, todo
Bean debe tener un Constructor por defecto, es decir, un constructor sin parametros,
puede tener muchos constructores, con parametros de todo tipo, pero debe existir el
por defecto, tambien debe haber un metodo set y get para cada atributo del Bean, etc.
import java.io.Serializable;
public class Usuario implements Serializable{
private static final long serialVersionUID = -288704532736952222L;
private String usuario;
private String contraseña;
private Boolean estado;
private String perfil;
private String nombre;
private String identificacion;
public Usuario() {
// TODO Auto-generated constructor stub
}
public String getContraseña() {
return contraseña;
}
public void setContraseña(String contraseña) {
this.contraseña = contraseña;
}
public Boolean getEstado() {
return estado;
}
public void setEstado(Boolean estado) {
this.estado = estado;
}
public String getIdentificacion() {
return identificacion;
}
public void setIdentificacion(String identificacion) {
this.identificacion = identificacion;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getPerfil() {
return perfil;
}
public void setPerfil(String perfil) {
this.perfil = perfil;
}
public String getUsuario() {
return usuario;
}
public void setUsuario(String usuario) {
this.usuario = usuario;
}
}
Para que un programa Java pueda convertir un objeto en un montón de bytes y pueda
luego recuperarlo, el objeto necesita ser Serializable. Al poder convertir el objeto a
bytes, ese objeto se puede enviar a través de red y después reconstruirlo al otro lado
de la red, guardarlo en un fichero y leerlo del fichero, etc.
Útil para implementar “persistencia” de objetos.
La interfaz no tiene métodos sirve sólo para identificar la semántica de que es
serializable.
Cualquier subclase de una clase serializable también lo es.
Este proceso no solo salva una imagen del objeto sino que también, de manera
recursiva, guarda todas las referencias que contiene dicho objeto.
Si está serializando en el mismo Stream se recuperará la misma estructura de
objetos sin duplicados.
Cuando pasamos objetos Serializable de un lado a otro tenemos un pequeño
problema. Si la clase que queremos pasar es objeto_serializable, lo normal, salvo que
usemos Carga dinámica de clases, es que en ambos lados (el que envía y el que
recibe la clase), tengan su propia copia del fichero objeto_serializable.class. Es posible
que en distintas versiones de nuestro programa la clase objeto_serializable cambie, de
forma que es posible que un lado tenga una versión más antigua que en el otro lado.
Si sucede esto, la reconstrucción de la clase en el lado que recibe es imposible.
Para evitar este problema, se aconseja que la clase objeto_serializable tenga un
atributo privado de esta forma:
private static final long serialVersionUID = -288704532736952222L;
De forma que el numerito que ponemos al final debe ser distinto para cada versión de
compilado que tengamos.
De esta forma, Java es capaz de detectar rápidamente que las versiones de
objeto_serializable.class en ambos lados son distintas. En Eclipse basta con hacer
click con el ratón sobre el símbolo de warning para que nos de las posibles soluciones
al warning. Una de ellas genera el número automáticamente.
5.7. Look and Feel
Normalmente las ventanas Java tienen su propio aspecto, su propio estilo de botones
y demás. Con java es muy fácil cambiar el aspecto (look and feel o skin) de nuestras
ventanas para que tengan aspecto Java, aspecto windows, etc. Basta con tener la
librería adecuada y una sola línea de código.
Para obtener el aspecto de ventanas propio del sistema operativo en el que estemos
(windows xp, solaris, etc), basta con estas líneas de código antes de crear ninguna
ventana:
try {
UIManager.setLookAndFeel("com.jgoodies.looks.windows.WindowsLookAndFeel");
} catch (Exception ex) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e){}
}
Con UIManager.getSystemLookAndFeelClassName() obtenemos el nombre del Look
and Feel por defecto del sistema operativo en el que estemos. Con
UIManager.setLookAndFeel decimos qué Look and Feel queremos.
5.8. Archivos de Properties
El API de Java contiene la clase Properties que nos permite hacer todo lo que
queremos, que es crear ficheros de configuración complejos y manejarlos con
facilidad. Un fichero .properties nos permite hacer casi todo lo que deseamos mientras
respetemos el formato clave = valor (o valores).
IMG-STEP-ACTIVE = /imagenes/step_48x48_active.png
IMG-STEP-INACTIVE = /imagenes/step_48x48_inactive.png
IMG-STEP-INACTIVE_PAST = /imagenes/step_48x48_inactive_past.png
IMG-STEP-INACTIVE_END = /imagenes/step_48x48_inactive_end.png
IMG-STEP-ACTIVE_INITIAL = /imagenes/step_48x48_active_initial.png
IMG-STEP-ACTIVE_END = /imagenes/step_48x48_active_end.png
IMG-STEP-LINE-ACTIVE = /imagenes/stepline_48x28_active.png
IMG-STEP-LINE-INACTIVE = /imagenes/stepline_48x28_inactive.png
IMG-OK = /imagenes/disk_blue_ok_48x48.png
Para leer los datos del fichero solo necesitamos crear un InputStream. A continuancion
una clase que permite leer la ruta de cada imagen del archivo de properties anterior. El
nombre del archivo es: IconoImagen.properties.
import java.io.InputStream;
import java.util.Properties;
import javax.swing.ImageIcon;
public class Imagen {
private static Properties properties = new Properties();
public static ImageIcon getIconoImagen(String codigo) {
ImageIcon resultado = null;
String path = null;
if(codigo == null){
return null;
}
try{
if(properties.isEmpty()) {
InputStream stream =
Imagen.class.getResourceAsStream("IconoImagen.properties");
if (stream == null){
return null;
}
properties.load(stream);
stream.close();
}
path = properties.getProperty(codigo);
if (path == null){
return null;
}
path = path.trim();
resultado = new ImageIcon(Imagen.class.getResource(path));
}
catch (Exception exception){
exception.printStackTrace();
}
return resultado;
}
}
El método getIconoImagen recibe un parámetro de tipo String que es la clave de la
imagen y retorna un objeto de tipo ImageIcon.
protected JButton getAgregarButton() {
if (agregarButton == null) {
agregarButton = new JButton();
agregarButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
setDatos();
}
});
}
agregarButton.setIcon(Imagen.getIconoImagen("IMG-OK"));
return agregarButton;
}
5.9. Tablas y Modelos
El JTable es un objeto muy potente y complejo a la vez, la mayoría de objetos SWING
manejan el paradigma vista/controlador. Este paradigma básicamente consiste en que
debe haber un objeto encargado de manipular y operar los datos y otro objeto es el
encargado de presentarlos.
El objeto JTable al utilizar el modelo vista controlador necesita de un objeto derivado
de AbstractTableModel para poder realizar la gestión de los datos.
import java.io.Serializable;
public class Cliente implements Serializable {
private static final long serialVersionUID = 1257318183448741500L;
private Integer codigo = null;
private String nombre = null;
private String apellido = null;
private String telefono = null;
private String direccion = null;
public Cliente() {
// TODO Auto-generated constructor stub
}
public Integer getCodigo() {
return codigo;
}
public void setCodigo(Integer codigo) {
this.codigo = codigo;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getApellido() {
return apellido;
}
public void setApellido(String apellido) {
this.apellido = apellido;
}
public String getTelefono() {
return telefono;
}
public void setTelefono(String telefono) {
this.telefono = telefono;
}
public String getDireccion() {
return direccion;
}
public void setDireccion(String direccion) {
this.direccion = direccion;
}
}
import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;
import aplicacion.Cliente;
public class ClienteTableModel extends AbstractTableModel{
private static List<String> columns = new ArrayList<String>();
private List<Cliente> cliente = new ArrayList<Cliente>();
static {
columns.add("Código");
columns.add("Nombre");
columns.add("Apellido");
columns.add("Dirección");
columns.add("Teléfono");
}
public String getColumnName(int col) {
return columns.get(col);
}
public Class getColumnClass(int c) {
return String.class;
}
public int getColumnCount() {
return columns.size();
}
public int getRowCount() {
return cliente.size();
}
public Object getValueAt(int row, int col) {
Cliente cliente = this.cliente.get(row);
switch (col) {
case 0:
return cliente.getCodigo();
case 1:
return cliente.getNombre();
case 2:
return cliente.getApellido();
case 3:
return cliente.getDireccion();
case 4:
return cliente.getTelefono();
default:
return null;
}
}
public void setValueAt(Object value, int row, int col) {
Cliente cliente = this.cliente.get(row);
switch (col) {
case 0:
cliente.setCodigo(Integer.parseInt(value.toString()));break;
case 1:
cliente.setNombre(value.toString());break;
case 2:
cliente.setApellido(value.toString());break;
case 3:
cliente.setDireccion(value.toString());break;
case 4:
cliente.setTelefono(value.toString());break;
default:
break;
}
}
public List<Cliente> getCliente() {
return cliente;
}
public void setCliente(List<Cliente> cliente) {
this.cliente = cliente;
}
}
Para la clase ClienteTableModel se implementaron los siguientes métodos de la clase
abstracta AbstractTableModel:
public String getColumnName(int col). Devuelve el nombre de la columna.
public Class getColumnClass(int col). Devuelve la clase que corresponde al
tipo de columna.
public int getColumnCount(). Devuelve el número de columnas.
public int getRowCount(). Devuelve el número de filas.
public Object getValueAt (int row, int col). Permite leer el valor de la celda
especificada por la fila y columna (Recordar que la fila y columna empiezan por
0) esto objeto nos devolverá un tipo de datos Object el cual deberá ser
interpretado de manera adecuada por nuestro programa.
public void setValueAt (Object value, int row, int col). Permite modificar un valor
especificando la fila y columna del JTable.
public boolean isCellEditable (int row, int col). Es el encargado de especificar
cuando una celda se puede editar tomando como parámetros la fila y la
columna.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import wizard.Imagen;
import aplicacion.Cliente;
public class ClientePanel1 extends JPanel{
private JButton agregarButton;
private JTextField telefonoTextField;
private JLabel telefonoLabel;
private JTextField direccionTextField;
private JLabel direccionLabel;
private JTextField apellidoTextField;
private JLabel apellidoLabel;
private JTextField nombreTextField;
private JTextField codigoTextField;
private JLabel nombreLabel;
private JLabel codigoLabel;
private JPanel compoesntesPanel;
private ClaseTable clienteTable;
private JScrollPane clientesScrollPane;
public ClientePanel1() {
super();
setLayout(new BorderLayout());
add(getClientesScrollPane());
add(getCompoesntesPanel(), BorderLayout.SOUTH);
}
protected JScrollPane getClientesScrollPane() {
if (clientesScrollPane == null) {
clientesScrollPane = new JScrollPane();
clientesScrollPane.setViewportView(getClienteTable());
}
return clientesScrollPane;
}
protected ClaseTable getClienteTable() {
if (clienteTable == null) {
clienteTable = new ClaseTable();
ClienteTableModel modelo = new ClienteTableModel();
clienteTable.setModel(modelo);
}
return clienteTable;
}
protected JPanel getCompoesntesPanel() {
if (compoesntesPanel == null) {
compoesntesPanel = new JPanel();
compoesntesPanel.setLayout(new GridBagLayout());
compoesntesPanel.setSize(500, 120);
compoesntesPanel.setPreferredSize(new Dimension(0, 120));
final GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.insets = new Insets(12, 66, 2, 15);
compoesntesPanel.add(getCodigoLabel(), gridBagConstraints);
final GridBagConstraints gridBagConstraints_4 = new GridBagConstraints();
gridBagConstraints_4.gridx = 1;
gridBagConstraints_4.gridy = 0;
gridBagConstraints_4.ipadx = 110;
gridBagConstraints_4.insets = new Insets(10, 17, 0, 86);
compoesntesPanel.add(getCodigoTextField(), gridBagConstraints_4);
final GridBagConstraints gridBagConstraints_8 = new GridBagConstraints();
gridBagConstraints_8.gridx = 2;
gridBagConstraints_8.gridy = 0;
gridBagConstraints_8.insets = new Insets(12, 7, 2, 0);
compoesntesPanel.add(getTelefonoLabel(), gridBagConstraints_8);
final GridBagConstraints gridBagConstraints_9 = new GridBagConstraints();
gridBagConstraints_9.anchor = GridBagConstraints.EAST;
gridBagConstraints_9.gridx = 3;
gridBagConstraints_9.gridy = 0;
gridBagConstraints_9.ipadx = 80;
gridBagConstraints_9.insets = new Insets(10, 12, 0, 20);
compoesntesPanel.add(getTelefonoTextField(), gridBagConstraints_9);
final GridBagConstraints gridBagConstraints_1 = new GridBagConstraints();
gridBagConstraints_1.gridx = 0;
gridBagConstraints_1.gridy = 1;
gridBagConstraints_1.insets = new Insets(8, 66, 2, 9);
compoesntesPanel.add(getNombreLabel(), gridBagConstraints_1);
final GridBagConstraints gridBagConstraints_2 = new GridBagConstraints();
gridBagConstraints_2.gridx = 0;
gridBagConstraints_2.gridy = 2;
gridBagConstraints_2.insets = new Insets(8, 66, 2, 9);
compoesntesPanel.add(getApellidoLabel(), gridBagConstraints_2);
final GridBagConstraints gridBagConstraints_3 = new GridBagConstraints();
gridBagConstraints_3.gridx = 0;
gridBagConstraints_3.gridy = 3;
gridBagConstraints_3.insets = new Insets(8, 66, 14, 0);
compoesntesPanel.add(getDireccionLabel(), gridBagConstraints_3);
final GridBagConstraints gridBagConstraints_5 = new GridBagConstraints();
gridBagConstraints_5.gridx = 1;
gridBagConstraints_5.gridy = 1;
gridBagConstraints_5.ipadx = 196;
gridBagConstraints_5.insets = new Insets(6, 17, 0, 0);
compoesntesPanel.add(getNombreTextField(), gridBagConstraints_5);
final GridBagConstraints gridBagConstraints_6 = new GridBagConstraints();
gridBagConstraints_6.gridx = 1;
gridBagConstraints_6.gridy = 2;
gridBagConstraints_6.ipadx = 196;
gridBagConstraints_6.insets = new Insets(6, 17, 0, 0);
compoesntesPanel.add(getApellidoTextField(), gridBagConstraints_6);
final GridBagConstraints gridBagConstraints_7 = new GridBagConstraints();
gridBagConstraints_7.gridx = 1;
gridBagConstraints_7.gridy = 3;
gridBagConstraints_7.ipadx = 196;
gridBagConstraints_7.insets = new Insets(6, 17, 12, 0);
compoesntesPanel.add(getDireccionTextField(), gridBagConstraints_7);
final GridBagConstraints gridBagConstraints_10 = new GridBagConstraints();
gridBagConstraints_10.gridx = 3;
gridBagConstraints_10.gridy = 1;
gridBagConstraints_10.gridheight = 3;
gridBagConstraints_10.ipady = 10;
gridBagConstraints_10.insets = new Insets(6, 12, 12, 13);
compoesntesPanel.add(getAgregarButton(), gridBagConstraints_10);
}
return compoesntesPanel;
}
protected JLabel getCodigoLabel() {
if (codigoLabel == null) {
codigoLabel = new JLabel();
codigoLabel.setText("Código");
}
return codigoLabel;
}
protected JLabel getNombreLabel() {
if (nombreLabel == null) {
nombreLabel = new JLabel();
nombreLabel.setText("Nombre");
}
return nombreLabel;
}
protected JTextField getCodigoTextField() {
if (codigoTextField == null) {
codigoTextField = new JTextField();
}
return codigoTextField;
}
protected JTextField getNombreTextField() {
if (nombreTextField == null) {
nombreTextField = new JTextField();
}
return nombreTextField;
}
protected JLabel getApellidoLabel() {
if (apellidoLabel == null) {
apellidoLabel = new JLabel();
apellidoLabel.setText("Apellido");
}
return apellidoLabel;
}
protected JTextField getApellidoTextField() {
if (apellidoTextField == null) {
apellidoTextField = new JTextField();
}
return apellidoTextField;
}
protected JLabel getDireccionLabel() {
if (direccionLabel == null) {
direccionLabel = new JLabel();
direccionLabel.setText("Dirección");
}
return direccionLabel;
}
protected JTextField getDireccionTextField() {
if (direccionTextField == null) {
direccionTextField = new JTextField();
}
return direccionTextField;
}
protected JLabel getTelefonoLabel() {
if (telefonoLabel == null) {
telefonoLabel = new JLabel();
telefonoLabel.setText("Telefono");
}
return telefonoLabel;
}
protected JTextField getTelefonoTextField() {
if (telefonoTextField == null) {
telefonoTextField = new JTextField();
}
return telefonoTextField;
}
protected JButton getAgregarButton() {
if (agregarButton == null) {
agregarButton = new JButton();
agregarButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
setDatos();
}
});
}
agregarButton.setIcon(Imagen.getIconoImagen("IMG-OK"));
return agregarButton;
}
private void setDatos(){
Cliente cliente = null;
ClienteTableModel modelo = null;
if(getCodigoTextField().getText().trim().equals("") ||
getNombreTextField().getText().trim().equals("") ||
getApellidoTextField().getText().trim().equals("") ||
getDireccionTextField().getText().trim().equals("") ||
getTelefonoTextField().getText().trim().equals("")){
JOptionPane.showMessageDialog(this,
"Faltas campos que son obligatorios.",
"Información",
JOptionPane.INFORMATION_MESSAGE
);
return;
}
cliente = new Cliente();
cliente.setCodigo(Integer.parseInt(getCodigoTextField().getText()));
cliente.setNombre(getNombreTextField().getText());
cliente.setApellido(getApellidoTextField().getText());
cliente.setDireccion(getDireccionTextField().getText());
cliente.setTelefono(getTelefonoTextField().getText());
modelo = (ClienteTableModel) this.getClienteTable().getModel();
for(Cliente cli : modelo.getCliente()){
if(cli.getCodigo().intValue() == cliente.getCodigo().intValue()){
JOptionPane.showMessageDialog(this,
"El código ya existe.",
"Error",
JOptionPane.ERROR_MESSAGE
);
return;
}
}
modelo.getCliente().add(cliente);
modelo.fireTableDataChanged();
getCodigoTextField().setText("");
getNombreTextField().setText("");
getApellidoTextField().setText("");
getDireccionTextField().setText("");
getTelefonoTextField().setText("");
}
}
En el método getClienteTable se construye la tabla y se instancia la clase
ClienteTableModel y se setea el modelo a la tabla con el método setModel.
protected ClaseTable getClienteTable() {
if (clienteTable == null) {
clienteTable = new ClaseTable();
ClienteTableModel modelo = new ClienteTableModel();
clienteTable.setModel(modelo);
}
return clienteTable;
}
El método setDatos permite validar que las cajas de texto que no estén vacias y
código del registro que se inserta en la tabla. Se crea un objeto Cliente con los datos
de las cajas de texto y se agregar a lista getCliente del modelo. Para que el modelo
detecte los cambios y el nuevo registro agregado se llama al método
fireTableDataChanged().
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.JDialog;
import javax.swing.UIManager;
import clases.ClientePanel1;
public class ClienteDialog extends JDialog {
private ClientePanel1 clientePanel1;
public ClienteDialog() {
super();
getContentPane().add(getClientePanel1(), BorderLayout.CENTER);
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
this.setSize(new Dimension(550,500));
this.setLocationRelativeTo(null);
}
protected ClientePanel1 getClientePanel1() {
if (clientePanel1 == null) {
clientePanel1 = new ClientePanel1();
}
return clientePanel1;
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("com.jgoodies.looks.windows.WindowsLookAndFeel");
} catch (Exception ex) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e){}
}
new ClienteDialog().setVisible(true);
}
}
5.10. Barras de Menú y Menús Contextuales
Primero creamos las acciones para nuestro menú, cada uno de los items. Para ello,
hacemos clases que hereden de AbstractAction.
private NuevoAction nuevoAction = null;
private EditarAction editarAction = null;
private EliminarAction eliminarAction = null;
public class NuevoAction extends AbstractAction {
public NuevoAction() {
super("Nuevo...", Imagen.getIconoImagen("IMG_NUEVO"));
}
public void actionPerformed(ActionEvent arg0) {
nuevo();
}
}
public class EditarAction extends AbstractAction {
public EditarAction() {
super("Editar...", Imagen.getIconoImagen("IMG_EDITAR"));
}
public void actionPerformed(ActionEvent arg0) {
editar();
}
}
public class EliminarAction extends AbstractAction {
public EliminarAction() {
super("Eliminar...", Imagen.getIconoImagen("IMG_ELIMINAR"));
}
public void actionPerformed(ActionEvent arg0) {
eliminar();
}
}
El objeto JToobar permite crear una barra de herramientas en nuestras aplicaciones
Java.
public void mostrarToolbar(){
JToolBar toolBar = null;
JButton button = null;
toolBar = new JToolBar();
toolBar.setBorder(new MatteBorder(0, 0, 0, 0, Color.black));
toolBar.setPreferredSize(new Dimension(50, 27));
toolBar.setRollover(true);
toolBar.setFloatable(true);
nuevoAction = new NuevoAction();
button = new JButton(nuevoAction);
button.setHorizontalAlignment(SwingConstants.LEFT);
toolBar.add(button);
editarAction = new EditarAction();
button = new JButton(editarAction);
button.setHorizontalAlignment(SwingConstants.LEFT);
toolBar.add(button);
eliminarAction = new EliminarAction();
button = new JButton(eliminarAction);
button.setHorizontalAlignment(SwingConstants.LEFT);
toolBar.add(button);
this.add(toolBar, BorderLayout.NORTH);
}
En el método mostrarToolbar se crea una JToolbar y se crean las diferentes acciones
de las clases NuevoAction, EditarAction y EliminarAction. Estas acciones se agregar a
un JButton y el JButton se agrega a la Toolbar.
Para generar un menú contextual en una tabla, se recomienda crear una clase aparte
(por ejemplo ClaseTable) que hereda de una JTable y que implementa la siguiente
estructura de código.
this.addMouseListener(
new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) showPopUpMenu(e.getPoint());
}
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()) showPopUpMenu(e.getPoint());
}
}
);
private void showPopUpMenu(Point p) {
updateSelection(p);
JPopupMenu menu = new JPopupMenu();
List<AbstractAction> actions = getActions();
if(actions != null){
for(AbstractAction action: getActions()){
menu.add(action);
}
updateActions();
if (menu != null) menu.show(this, p.x, p.y);
}
}
private void updateSelection(Point p) {
int nRow = rowAtPoint(p);
if (nRow == -1) clearSelection();
else if (!isRowSelected(nRow))
getSelectionModel().setSelectionInterval(nRow, nRow);
}
public List<AbstractAction> getActions() {
return null;
}
public void updateActions() {
}
El componente Java para el menú contextual es un JPopupMenu. Sólo hay que
instanciarlo y por medio del método add() pasarle las acciones que queremos que
sean nuestros items del menú. Por supuesto, hay más métodos para añadir las
acciones de otra forma o para añadir incluso submenus. Los métodos getActions y
updateActions serán sobrescritos en la clase que extienda de ClaseTable.
A contunuacion el código completo de estas clases.
La claseTable tiene propiedades adiciones de una JTable norma. Implementa las
interfaces DropTargetListener y DragGestureListener que se trataran mas adelante y
permite tener métodos como adjustColumnWidth() que permite adjustar las columnas
al tamaño de información que existe en las celdas y también el manejo del Objeto
JPopupMenu para los menus contextuales.
public class ClaseTable extends JTable implements DropTargetListener,
DragGestureListener{
protected DropTarget dropTarget = null;
protected DragSource dragSource = null;
public ClaseTable() {
super();
initTable();
}
private void initTable() {
setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
putClientProperty("JTable.autoStartsEdit", Boolean.FALSE);
this.addMouseListener(
new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) showPopUpMenu(e.getPoint());
}
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()) showPopUpMenu(e.getPoint());
}
}
);
putClientProperty("JTable.autoStartsEdit", Boolean.FALSE);
dropTarget = new DropTarget(this, this);
dragSource = new DragSource();
dragSource.createDefaultDragGestureRecognizer(this,
DnDConstants.ACTION_COPY_OR_MOVE, this);
}
private void updateSelection(Point p) {
int nRow = rowAtPoint(p);
if (nRow == -1) clearSelection();
else if (!isRowSelected(nRow))
getSelectionModel().setSelectionInterval(nRow, nRow);
}
private void showPopUpMenu(Point p) {
updateSelection(p);
JPopupMenu menu = new JPopupMenu();
List<AbstractAction> actions = getActions();
if(actions != null){
for(AbstractAction action: getActions()){
menu.add(action);
}
updateActions();
if (menu != null) menu.show(this, p.x, p.y);
}
}
public List<AbstractAction> getActions() {
return null;
}
public void updateActions() {
}
public void adjustColumnWidth(){
TableColumnModel columnModel = this.getColumnModel();
int totalColumn = this.getColumnCount();
int totalRows = this.getRowCount();
for(int column=0; column<totalColumn; column++){
int maxSize =0;
for(int row=0; row<totalRows; row++){
TableCellRenderer rend= getCellRenderer(row, column);
Object cellValue= getValueAt(row, column);
Component mintComponent= rend.getTableCellRendererComponent(this, cellValue,
false, false, row, column);
if (!(mintComponent instanceof JPanel)) {
mintComponent.setPreferredSize(null);
}
maxSize= Math.max(mintComponent.getPreferredSize().width,maxSize);
}
TableColumn tableColumn= columnModel.getColumn(column);
TableCellRenderer headerRenderer= tableColumn.getHeaderRenderer();
if(headerRenderer==null){
headerRenderer = getTableHeader().getDefaultRenderer();
}
Object headerValue=tableColumn.getHeaderValue();
Component headerComp= headerRenderer.getTableCellRendererComponent(this,
headerValue,
false,
false, 0,
column);
int tHeader=headerComp.getPreferredSize().width;
maxSize= Math.max(maxSize,tHeader)+4;
tableColumn.setPreferredWidth(maxSize);
tableColumn.setMinWidth(4);
}
}
public boolean getScrollableTracksViewportHeight() {
Component parent = getParent();
if (parent instanceof JViewport)
return parent.getHeight() > getPreferredSize().height;
return false;
}
public void dragEnter(DropTargetDragEvent dtde) {}
public void dragExit(DropTargetEvent dte) {}
public void dragOver(DropTargetDragEvent dtde) {}
public void drop(DropTargetDropEvent dtde) {}
public void dropActionChanged(DropTargetDragEvent dtde) {}
public void dragGestureRecognized(DragGestureEvent dge){}
}
La clase ClienteTable extiende de ClaseTable que a su vez extiende de una JTable.
Esta clase permite implementar las acciones que tendrá la tabla en el menú
contextual.
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
public class ClienteTable extends ClaseTable {
private List<AbstractAction> actions = null;
private NuevoAction nuevoAction = null;
private EditarAction editarAction = null;
private EliminarAction eliminarAction = null;
public ClienteTable() {
super();
}
public class NuevoAction extends AbstractAction {
public NuevoAction() {
super("Nuevo...", Imagen.getIconoImagen("IMG_NUEVO"));
}
public void actionPerformed(ActionEvent arg0) {
ClienteTable.this.firePropertyChange("nuevo", true, false);
}
}
public class EditarAction extends AbstractAction {
public EditarAction() {
super("Editar...", Imagen.getIconoImagen("IMG_EDITAR"));
}
public void actionPerformed(ActionEvent arg0) {
ClienteTable.this.firePropertyChange("editar", true, false);
}
}
public class EliminarAction extends AbstractAction {
public EliminarAction() {
super("Eliminar...",Imagen.getIconoImagen("IMG_ELIMINAR"));
}
public void actionPerformed(ActionEvent arg0) {
ClienteTable.this.firePropertyChange("eliminar", true, false);
}
}
public List<AbstractAction> getActions(){
if(actions == null){
actions = new ArrayList<AbstractAction>();
}
if(nuevoAction == null){
nuevoAction = new NuevoAction();
actions.add(nuevoAction);
}
if(editarAction == null){
editarAction = new EditarAction();
actions.add(editarAction);
}
if(eliminarAction == null){
eliminarAction = new EliminarAction();
actions.add(eliminarAction);
}
return actions;
}
public void updateActions() {
int row = this.getSelectedRow();
if(editarAction != null){
editarAction.setEnabled(row > -1);
}
if(eliminarAction != null){
eliminarAction.setEnabled(row > -1);
}
}
}
Se sobreescribe los métodos getActions que permite crear las acciones y agregarlas a
una lista de AbstractAction, este método es invocado por la clase padre en este caso
“ClaseTable” cuando el usuario da clic izquierdo con el mouse y el método
updateActions que permite activar o desactivar la acción. En esta clase también se
hace uso del firePropertyChange que permite lanzar un listener a la clase donde se
este usando la tabla “ClienteTable”.
La clase “ClientePanel2” permite implementar las acciones para la barra de menú y
además construye el GUI general. Se hace uso de la interfaz
addPropertyChangeListener que permite escuchar el firePropertyChange que fue
lanzado desde la clase “ClienteTable”.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.KeyboardFocusManager;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.border.MatteBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import aplicacion.Cliente;
public class ClientePanel2 extends JPanel{
private ClienteTable clienteTable;
private JScrollPane clientesScrollPane;
private NuevoAction nuevoAction = null;
private EditarAction editarAction = null;
private EliminarAction eliminarAction = null;
public ClientePanel2() {
super();
setLayout(new BorderLayout());
add(getClientesScrollPane());
mostrarToolbar();
updateActions();
}
protected JScrollPane getClientesScrollPane() {
if (clientesScrollPane == null) {
clientesScrollPane = new JScrollPane();
clientesScrollPane.setViewportView(getClienteTable());
}
return clientesScrollPane;
}
protected ClienteTable getClienteTable() {
if (clienteTable == null) {
clienteTable = new ClienteTable();
clienteTable.addMouseListener(new MouseAdapter() {
public void mouseClicked(final MouseEvent evt) {
if(editarAction.isEnabled() && evt.getClickCount() == 2){
editar();
}
}
});
ClienteTableModel modelo = new ClienteTableModel();
clienteTable.setModel(modelo);
ListSelectionModel listSelectionModel = clienteTable.getSelectionModel();
listSelectionModel.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
updateActions();
}
});
clienteTable.addPropertyChangeListener(new PropertyChangeListener(){
public void propertyChange(PropertyChangeEvent evt) {
if(evt.getPropertyName().equals("nuevo")){
nuevo();
}
else if(evt.getPropertyName().equals("editar")){
editar();
}
else if(evt.getPropertyName().equals("eliminar")){
eliminar();
}
}
});
}
return clienteTable;
}
public class NuevoAction extends AbstractAction {
public NuevoAction() {
super("Nuevo...", Imagen.getIconoImagen("IMG_NUEVO"));
}
public void actionPerformed(ActionEvent arg0) {
nuevo();
}
}
public class EditarAction extends AbstractAction {
public EditarAction() {
super("Editar...", Imagen.getIconoImagen("IMG_EDITAR"));
}
public void actionPerformed(ActionEvent arg0) {
editar();
}
}
public class EliminarAction extends AbstractAction {
public EliminarAction() {
super("Eliminar...", Imagen.getIconoImagen("IMG_ELIMINAR"));
}
public void actionPerformed(ActionEvent arg0) {
eliminar();
}
}
private void nuevo(){
nuevoOeditar(null);
}
private void editar(){
ClienteTableModel modelo = (ClienteTableModel) clienteTable.getModel();
nuevoOeditar(modelo.getCliente().get(clienteTable.getSelectedRow()));
}
private void eliminar(){
ClienteTableModel modelo = (ClienteTableModel) clienteTable.getModel();
modelo.getCliente().remove(clienteTable.getSelectedRow());
modelo.fireTableDataChanged();
}
public void mostrarToolbar(){
JToolBar toolBar = null;
JButton button = null;
toolBar = new JToolBar();
toolBar.setBorder(new MatteBorder(0, 0, 0, 0, Color.black));
toolBar.setPreferredSize(new Dimension(50, 27));
toolBar.setRollover(true);
toolBar.setFloatable(true);
nuevoAction = new NuevoAction();
button = new JButton(nuevoAction);
button.setHorizontalAlignment(SwingConstants.LEFT);
toolBar.add(button);
editarAction = new EditarAction();
button = new JButton(editarAction);
button.setHorizontalAlignment(SwingConstants.LEFT);
toolBar.add(button);
eliminarAction = new EliminarAction();
button = new JButton(eliminarAction);
button.setHorizontalAlignment(SwingConstants.LEFT);
toolBar.add(button);
this.add(toolBar, BorderLayout.NORTH);
}
private void updateActions(){
int row = getClienteTable().getSelectedRow();
if(editarAction != null){
editarAction.setEnabled(row > -1);
}
if(eliminarAction != null){
eliminarAction.setEnabled(row > -1);
}
}
public void nuevoOeditar(final Cliente cliente){
Window window =
KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
final int fila = getClienteTable().getSelectedRow();
final EditDialog editDialog = EditDialog.ejecutar(window,
cliente);
editDialog.addPropertyChangeListener(new PropertyChangeListener(){
public void propertyChange(PropertyChangeEvent evt){
if(evt.getPropertyName().equals("guardar")){
ClienteTableModel modelo = (ClienteTableModel) clienteTable.getModel();
if(cliente == null){
for(Cliente cli : modelo.getCliente()){
if(cli.getCodigo().intValue() == ((Cliente)
evt.getNewValue()).getCodigo().intValue()){
JOptionPane.showMessageDialog(ClientePanel2.this,
"El código ya existe.",
"Error",
JOptionPane.ERROR_MESSAGE
);
return;
}
}
modelo.getCliente().add((Cliente) evt.getNewValue());
modelo.fireTableDataChanged();
editDialog.dispose();
}
else{
modelo.getCliente().set(fila,(Cliente) evt.getNewValue());
modelo.fireTableDataChanged();
editDialog.dispose();
getClienteTable().setRowSelectionInterval(fila, fila);
}
}
}
});
editDialog.showCentered(0, 0);
}
}
El método “nuevoOeditar” de la clase “ClientePanel2” se llama cuando se da clic en el
menú contextual o en la barra de menú sobre las opciones Nuevo o Editar. Este
método laza un dialogo que permite agregar y modificar registros de la tabla.
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class EditarPanel extends JPanel {
private JLabel label;
private JTextField telefonoTextField;
private JButton agregarButton;
private JLabel telefonoLabel;
private JTextField direccionTextField;
private JLabel direccionLabel;
private JTextField apellidoTextField;
private JLabel apellidoLabel;
private JTextField nombreTextField;
private JLabel nombreLabel;
private JTextField codigoTextField;
private JLabel codigoLabel;
public EditarPanel() {
super();
setLayout(null);
setSize(500, 375);
add(getNombreLabel());
add(getApellidoLabel());
add(getDireccionLabel());
add(getNombreTextField());
add(getApellidoTextField());
add(getDireccionTextField());
add(getAgregarButton());
add(getLabel());
add(getCodigoLabel());
add(getCodigoTextField());
add(getTelefonoLabel());
add(getTelefonoTextField());
}
protected JLabel getCodigoLabel() {
if (codigoLabel == null) {
codigoLabel = new JLabel();
codigoLabel.setBounds(12, 63, 39, 16);
codigoLabel.setText("Código");
}
return codigoLabel;
}
protected JTextField getCodigoTextField() {
if (codigoTextField == null) {
codigoTextField = new JTextField();
codigoTextField.setBounds(83, 61, 114, 20);
}
return codigoTextField;
}
protected JLabel getNombreLabel() {
if (nombreLabel == null) {
nombreLabel = new JLabel();
nombreLabel.setBounds(12, 89, 45, 16);
nombreLabel.setText("Nombre");
}
return nombreLabel;
}
protected JTextField getNombreTextField() {
if (nombreTextField == null) {
nombreTextField = new JTextField();
nombreTextField.setBounds(83, 87, 200, 20);
}
return nombreTextField;
}
protected JLabel getApellidoLabel() {
if (apellidoLabel == null) {
apellidoLabel = new JLabel();
apellidoLabel.setBounds(12, 115, 45, 16);
apellidoLabel.setText("Apellido");
}
return apellidoLabel;
}
protected JTextField getApellidoTextField() {
if (apellidoTextField == null) {
apellidoTextField = new JTextField();
apellidoTextField.setBounds(83, 113, 200, 20);
}
return apellidoTextField;
}
protected JLabel getDireccionLabel() {
if (direccionLabel == null) {
direccionLabel = new JLabel();
direccionLabel.setBounds(12, 141, 54, 16);
direccionLabel.setText("Dirección");
}
return direccionLabel;
}
protected JTextField getDireccionTextField() {
if (direccionTextField == null) {
direccionTextField = new JTextField();
direccionTextField.setBounds(83, 139, 200, 20);
}
return direccionTextField;
}
protected JLabel getTelefonoLabel() {
if (telefonoLabel == null) {
telefonoLabel = new JLabel();
telefonoLabel.setBounds(290, 63, 49, 16);
telefonoLabel.setText("Telefono");
}
return telefonoLabel;
}
protected JButton getAgregarButton() {
if (agregarButton == null) {
agregarButton = new JButton();
agregarButton.setBounds(351, 87, 75, 72);
agregarButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
Cliente cliente = getCliente();
if(cliente != null){
EditarPanel.this.firePropertyChange("guardar", true, cliente);
}
}
});
agregarButton.setIcon(Imagen.getIconoImagen("IMG-OK"));
}
return agregarButton;
}
protected JTextField getTelefonoTextField() {
if (telefonoTextField == null) {
telefonoTextField = new JTextField();
telefonoTextField.setBounds(351, 61, 75, 20);
}
return telefonoTextField;
}
protected JLabel getLabel() {
if (label == null) {
label = new JLabel();
label.setBounds(162, 12, 177, 21);
label.setFont(new Font("", Font.BOLD, 16));
label.setText("New JLabel");
}
return label;
}
public void setTitulo(String titulo){
getLabel().setText(titulo);
}
public void setCliente(Cliente cliente){
if(cliente != null){
getCodigoTextField().setText(String.valueOf(cliente.getCodigo()));
getNombreTextField().setText(cliente.getNombre());
getApellidoTextField().setText(cliente.getApellido());
getDireccionTextField().setText(cliente.getDireccion());
getTelefonoTextField().setText(cliente.getTelefono());
}
}
private Cliente getCliente(){
if(getCodigoTextField().getText().trim().equals("") ||
getNombreTextField().getText().trim().equals("") ||
getApellidoTextField().getText().trim().equals("") ||
getDireccionTextField().getText().trim().equals("") ||
getTelefonoTextField().getText().trim().equals("")){
JOptionPane.showMessageDialog(this,
"Faltas campos que son obligatorios.",
"Información",
JOptionPane.INFORMATION_MESSAGE
);
return null;
}
Cliente cliente = new Cliente();
cliente.setCodigo(Integer.parseInt(getCodigoTextField().getText()));
cliente.setNombre(getNombreTextField().getText());
cliente.setApellido(getApellidoTextField().getText());
cliente.setDireccion(getDireccionTextField().getText());
cliente.setTelefono(getTelefonoTextField().getText());
return cliente;
}
}
import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JDialog;
public class EditDialog extends JDialog {
private EditarPanel editarPanel;
public EditDialog(Frame frame, Cliente cliente){
super(frame,true);
inicializar(cliente);
}
public EditDialog(Dialog dialog, Cliente cliente) {
super(dialog,true);
inicializar(cliente);
}
public EditDialog(Cliente cliente) {
this((Frame)null,cliente);
}
public static EditDialog ejecutar(Window window, Cliente cliente){
if (window instanceof Frame){
return new EditDialog((Frame) window ,cliente);
}
else if (window instanceof Dialog){
return new EditDialog((Dialog)window, cliente);
}
else{
return new EditDialog((Frame)null, cliente);
}
}
private void inicializar(Cliente cliente){
getContentPane().add(getEditarPanel(), BorderLayout.CENTER);
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setBounds(0, 0,460 , 205);
this.setResizable(false);
String titulo = cliente == null ? "Nuevo Cliente" :
"Editar Cliente";
this.setTitle(titulo);
getEditarPanel().setTitulo(titulo);
getEditarPanel().setCliente(cliente);
this.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent arg0) {
dispose();
}
});
}
protected EditarPanel getEditarPanel() {
if (editarPanel == null) {
editarPanel = new EditarPanel();
editarPanel.addPropertyChangeListener(new PropertyChangeListener(){
public void propertyChange(PropertyChangeEvent evt) {
if(evt.getPropertyName().equals("guardar")){
EditDialog.this.firePropertyChange("guardar", true,
evt.getNewValue());
}
}
});
}
return editarPanel;
}
public void showCentered(int xOffset, int yOffset) {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = getSize();
if (frameSize.height > screenSize.height){
frameSize.height = screenSize.height;
}
if (frameSize.width > screenSize.width){
frameSize.width = screenSize.width;
}
int nXPos = (screenSize.width - frameSize.width) / 2 + xOffset;
int nYPos = (screenSize.height - frameSize.height) / 2 + yOffset;
setLocation(nXPos, nYPos);
setVisible(true);
}
}
5.11. Drag-and-Drop
Para generar un drag-and-drop entre un componente y otro se debe implementar la
interfaz DragSourceListener donde se va hacer el drag y agregar la siguiente
estructura de código en el método constructor de la clase o en un método inicializar si
esta clase tiene varios constructores.
DragSource dragSource = new DragSource();
dragSource.createDefaultDragGestureRecognizer(this,
DnDConstants.ACTION_COPY_OR_MOVE, new DragGestureListener(){
public void dragGestureRecognized(DragGestureEvent e){
startDragTree(e);
}
});
El método startDragTree se llama cuando se presiona el clic derecho del mouse y se
arrastra.
private void startDragTree(DragGestureEvent e) {
TreePath[] selectedPaths = this.getSelectionPaths();
File files[] = null;
if(selectedPaths == null || selectedPaths.length == 0){
return;
}
files = new File[selectedPaths.length];
for(int i = 0; i<selectedPaths.length; i++){
files[i] = (File) selectedPaths[i].getLastPathComponent();
}
e.getDragSource().startDrag(
e,
DragSource.DefaultMoveDrop,
new TransferableTree(files),
this);
}
Para este ejemplo el método startDragTree permite capturar los nodos seleccionados
de un árbol. El objeto que se va a llevar para el drop se debe guardar en una clase que
debe implementa la interfaz Transferable, una clase que implemente está interfaz
puede manejar múltiples drag-and-drop.
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
public class TransferableTree implements Transferable {
final static int TREE = 0;
final public static DataFlavor TREE_FLAVOR = new DataFlavor(File[].class, "tree");
static DataFlavor fFlavors[] = {TREE_FLAVOR,
DataFlavor.stringFlavor};
private File[] file;
public TransferableTree(File[] file) {
this.file = file;
}
public DataFlavor[] getTransferDataFlavors() {
return fFlavors;
}
public Object getTransferData(DataFlavor aFlavor) throws UnsupportedFlavorException{
Object lReturnObject = null;
if (aFlavor.equals(fFlavors[TREE])) {
lReturnObject = file;
}
else {
throw new UnsupportedFlavorException(aFlavor);
}
return lReturnObject;
}
public boolean isDataFlavorSupported(DataFlavor aFlavor) {
boolean lReturnValue = false;
for (int i=0, n=fFlavors.length; i<n; i++) {
if (aFlavor.equals(fFlavors[i])) {
lReturnValue = true;
break;
}
}
return lReturnValue;
}
}
En la clase donde llega el drop se debe implementar las interfaces DropTargetListener,
DragGestureListener. Para este ejemplo se permite el drag-and-drop entre un árbol
que esta en un JScrollPane y una tabla que también esta en una JScrollPane. En la
ClaseTable se hace la implementación de esas interfaces y de la siguiente
estructurura de código en el método initTable que inicializa propiedades de la tabla.
protected DropTarget dropTarget = null;
protected DragSource dragSource = null;
dropTarget = new DropTarget(this, this);
dragSource = new DragSource();
dragSource.createDefaultDragGestureRecognizer(this,
DnDConstants.ACTION_COPY_OR_MOVE, this);
En la clase donde esta la tabla que extienda de ClaseTable se debe sobrescribir el
método drop, tenido en cuenta el TransferableTree ya que se puede tener varios de
estos.
protected ClaseTable getDetallesTable() {
if (detallesTable == null) {
detallesTable = new ClaseTable(){
public void drop(DropTargetDropEvent dtde) {
Transferable tr = dtde.getTransferable();
File[] file = null;
try {
if(tr.isDataFlavorSupported(TransferableTree.TREE_FLAVOR)){
file = (File[]) tr.getTransferData(TransferableTree.TREE_FLAVOR);
NodosTableModel modelo = (NodosTableModel) detallesTable.getModel();
for(int i=0; i<file.length; i++){
if(!modelo.getFiles().contains(file[i])){
modelo.getFiles().add(file[i]);
}
}
modelo.fireTableDataChanged();
}
}
catch (UnsupportedFlavorException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
dtde.acceptDrop(DnDConstants.ACTION_MOVE);
dtde.dropComplete(true);
}
};
NodosTableModel modelo = new NodosTableModel();
detallesTable.setModel(modelo);
}
return detallesTable;
}
5.12. DefaultTableCellRenderer y DefaultCellEditor
Un JTable de Java sabe manejar algunos de los datos standard de Java, sabe dibujar
celdas que contengan un String, un Integer, etc. Es posbible que en un momento dado
queramos hacer que nuestros datos se pinten de alguna manera distinta o que
tengamos datos que el JTable no sabe manejar, alguna clase propia. Por ejemplo,
podemos querer pintar iconos en las celdas del JTable, hacer que cambie el tipo de
letra, sus colores, etc.
Para ello el JTable nos proporciona la posibilidad de cambiar su TableCellRenderer , la
clase que sabe y se encarga de dibujar los datos que hay en cada celda. Podemos
hacer nuestro propio TableCellRenderer que dibuje de forma especial esos datos o
que entienda nuevos tipos de datos. Luego basta con pasarle este TableCellRenderer
al JTable .
import java.awt.Color;
import java.awt.Component;
import javax.swing.JPasswordField;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
public class UsuarioTableCellRenderer extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
this.setForeground(Color.BLACK);
this.setBackground(Color.WHITE);
this.setText(value == null ? "" : String.valueOf(value));
this.setToolTipText(value == null ? "“: String.valueOf (value));
this.setIcon(null);
this.setHorizontalTextPosition(SwingConstants.RIGHT);
if(column == 0){
this.setIcon(Imagen.getIconoImagen("IMG_USUARIO"));
}
if(isSelected){
this.setBackground(table.getSelectionBackground());
this.setForeground(table.getSelectionForeground());
}
if(column == 6){
JPasswordField passwordField = new JPasswordField();
passwordField.setText(value == null ? "" :String.valueOf(value));
passwordField.setBorder(null);
if(isSelected){
passwordField.setBackground(table.getSelectionBackground());
passwordField.setForeground(table.getSelectionForeground());
}
return passwordField;
}
return this;
}
}
Este renderer coloca tooltiptest a las celdas de las columnas de la tabla y permite
colocar una imagen para la primera columna de la tabla. Tambien retorna un
componente JPasswordField para la columna 6 de la tabla.
Para agregar el renderer a las columnas de la tabla se puede utilizar un ciclo for para
recorrer todas las columnas de la tabla.
for(int i=0; i<getUsuarioTable().getColumnCount()-1; i++){
getUsuarioTable().setDefaultRenderer(getUsuarioTable().getColumnClass(i), new
UsuarioTableCellRenderer());
}
Para colocar un JComboBox o un JChecBox en una celda de una tabla hacemos uso
de la clase DefaultCellEditor. Para la siguiente clase se implemento un JComboBox y
un JPasswordField.
import java.awt.Color;
import java.awt.Component;
import java.awt.SystemColor;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JPasswordField;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.border.LineBorder;
public class UsuarioTableCellEditor extends DefaultCellEditor{
private JTextField textoTextField;
private JPasswordField passwordField;
private JComboBox tipoUsuario;
private int col = 0;
public UsuarioTableCellEditor(){
super(new JTextField());
setClickCountToStart(1);
textoTextField = (JTextField) this.getComponent();
textoTextField.setBorder(new LineBorder(Color.BLACK));
llenarComboTipoUsuario();
}
protected JComboBox getTipoUsuarioComboBox(){
if(tipoUsuario == null){
tipoUsuario = new JComboBox();
tipoUsuario.setBorder(new LineBorder(Color.BLACK));
tipoUsuario.setBackground(SystemColor.control);
}
return tipoUsuario;
}
protected JPasswordField getPasswordField(){
if(passwordField == null){
passwordField = new JPasswordField();
passwordField.setBackground(SystemColor.control);
passwordField.setBorder(null);
}
return passwordField;
}
private void llenarComboTipoUsuario(){
DefaultComboBoxModel model = null;
model = new DefaultComboBoxModel();
for(ETipoUsuario tipoUsuario :ETipoUsuario.values()){
model.addElement(tipoUsuario);
}
getTipoUsuarioComboBox().setModel(model);
}
public Component getTableCellEditorComponent(JTable table, Object value, boolean
isSelected, int row, int col) {
this.col = col;
if(table.getSelectedRow() == -1){
return null;
}
if(col == 4){
getTipoUsuarioComboBox().setSelectedItem(value);
return getTipoUsuarioComboBox();
}
if(col == 6){
getPasswordField().setText(value == null ? "" : String.valueOf(value));
return getPasswordField();
}
textoTextField = (JTextField) super.getTableCellEditorComponent(table, value,
isSelected, row, col);
textoTextField.setText(value == null ? "" : String.valueOf(value));
return textoTextField;
}
public Object getCellEditorValue(){
if(col == 4){
return getTipoUsuarioComboBox().getSelectedItem();
}
if(col == 6){
return getPasswordField().getText();
}
return textoTextField.getText().toUpperCase();
}
}
El JComboBox se llena con los datos del siguiente enumerado:
public enum ETipoUsuario {
ADMINISTRADOR{
public int getId(){
return 1;
}
public String getNombre(){
return "Administrador";
}
},
EMPLEADO{
public int getId(){
return 2;
}
public String getNombre(){
return "Empleado";
}
};
public abstract int getId();
public abstract String getNombre();
}
Para agregar el cellEditor a las columnas de la tabla se puede utilizar un ciclo for para
recorrer todas las columnas de la tabla.
for(int i=0; i<getUsuarioTable().getColumnCount(); i++){
getUsuarioTable().setDefaultEditor(getUsuarioTable().getColumnClass(i),
new UsuarioTableCellEditor());
}
5.13. Ejemplos
El siguiente WIZARD permite ver en un solo JDialog los últimos cuatro ejemplo de:
Tablas y Molelos, Barras de Menú y Menús contextuales, Drag-and-drop y
DefaultTableCellRenderer y DefaultCellEditor. Este diálogo maneja una transición
entre los cuatro paneles. Los .jar que permiten este tipo de animaciones son:
AnimatedTransitions-0.11.jar y TimingFramework-1.0.jar.
import java.awt.BorderLayout;
import javax.swing.JComponent;
import org.jdesktop.animation.timing.Animator;
import org.jdesktop.animation.transitions.ScreenTransition;
import org.jdesktop.animation.transitions.TransitionTarget;
public class TransitionPanel extends JComponent implements TransitionTarget{
private Animator animator = null;
private ScreenTransition transition = null;
private JComponent component = null;
private int milliseconds = 1500;
private final float acceleration = 0.2f;
public TransitionPanel(JComponent component){
init(component);
}
public void init(JComponent component){
this.animator = new Animator(this.milliseconds);
this.transition = new ScreenTransition(this, this, this.animator);
this.animator.setAcceleration(this.acceleration);
this.animator.setDeceleration(this.acceleration);
this.setLayout(new BorderLayout());
this.add(component);
}
public void setupNextScreen(){
this.removeAll();
this.add(this.component);
}
public void startTransition(){
this.transition.start();
}
public void setComponent(JComponent component) {
this.component = component;
}
public Animator getAnimator() {
if(animator == null) {
animator = new Animator(this.milliseconds);
}
return animator;
}
public int getMilliseconds() {
return milliseconds;
}
}
Esta clase permite la transición entre los componetes del wizard. En el dialogo los
componentes inicialmente son agregados de esta manera.
private TransitionPanel transitionPanel;
private JComponent component;
private JComponent getComponente(){
if(component == null){
component = new JPanel();
component.setLayout(new BorderLayout());
}
return component;
}
public JPanel getContainerPanel() {
if(containerPanel == null) {
containerPanel = new JPanel();
containerPanel.setLayout(new BorderLayout());
getComponente().add(getStepGuidePanel(0), BorderLayout.NORTH);
getComponente().add(getClientePanel(), BorderLayout.CENTER);
transitionPanel = new TransitionPanel(getComponente());
containerPanel.add(transitionPanel, BorderLayout.CENTER);
}
return containerPanel;
}
this.add(getContainerPanel(), BorderLayout.CENTER);
El manejo de paso de un panel a otro se hace mediante esta estructura de codigo:
public void gotoStep(int step) {
this.currentStep = step;
this.component = null;
getComponente().add(getStepGuidePanel(step), BorderLayout.NORTH);
switch(step) {
case 0: getComponente().add(getClientePanel(), BorderLayout.CENTER);
break;
case 1: getComponente().add(getClientePanel2(), BorderLayout.CENTER);
break;
case 2: getComponente().add(getTreePanel(), BorderLayout.CENTER);
break;
case 3: getComponente().add(getPropiedadesPanel(), BorderLayout.CENTER);
default:
break;
}
transitionPanel.setComponent(getComponente());
transitionPanel.startTransition();
updateNavigationButtons();
getContainerPanel().repaint();
getContainerPanel().revalidate();
}
Sistema de Historias Clinicas
1. Diagrama de casos de uso
a. Especificación de Actores
Nombre Médico
Descripción Breve Registra, consulta y actualiza las historias clínicas
Características Registra diagnósticos
Consulta Historias clínicas
Consulta, registra y modifica procedimientos
Consulta, registra y modifica formulas
Relaciones Sistema de citas
Secretaria
Nombre Secretaria
Descripción Breve Persona encargada de hacer de los datos básicos de los pacientes
Características Registra información de los pacientes
Asigna citas
Relaciones Sistema de citas
Medico
Nombre Sistema de citas
Descripción Breve Sistema encargado de administrar los recursos para la asignación de citas
Características Registra citas
Consulta datos básicos
Genera reportes de las citas diarias
Relaciones Sistema de citas
Medico
Nombre Administrador
Descripción Breve Persona encargada de administrar el sistema de historias clínicas.
Características Administra los procedimientos
Administra la información de los medicamentos
Relaciones Sistema de citas
Medico
Secretaria
b. Especificación de Caso de Uso
Nombre Registro paciente
Descripción Representa el caso de uso por medio del cual el actor va a realizar el registro de la historia clínica del paciente.
Flujo de eventos Flujo Básico
Ingresar la identificación del paciente. El actor ingresa el dato de la identificación, dicha identificación es el número de identificación del paciente que este registrado en el sistema de citas (cedula de ciudadanía, pasaporte, cedula de extranjería, etc.)
El sistema valida la identificación y muestra la pantalla con el formulario para llenar: Dicho formulario se compone por los siguientes datos:
o Identificación: Este campo representa la identificación del paciente (cedula de ciudadanía, pasaporte, cedula de extranjería, etc.)
o Nombre: Este campo representa el nombre completo del paciente
o Estatura: Este campo representa la estatura del paciente o Tipo de sangre: Este campo representa el tipo de sangre del
paciente o Ocupación: Este campo representa la ocupación actual del
paciente o Fecha de nacimiento: Este campo representa la fecha de
nacimiento del paciente
o Dirección: Este campo representa la dirección actual del paciente
o Peso: Este campo representa el peso en kilogramos del paciente.
La secretaria ingresa los datos al sistema
El sistema valida los datos y guarda la historia clínica terminando el proceso.
Flujos Alternativos Flujo alternativo historia existente A partir del paso 1 del flujo básico, el sistema valida la identificación mostrando el mensaje “Historia Clínica existente”
Flujo alternativo datos inválidos A partir del paso 3 del flujo básico, el sistema valida los datos mostrando un mensaje de error “No se puede registrar la información debido a que existen datos inválidos”, con el cual se le indica al actor que existen datos inválidos y sigue mostrando la pantalla actual.
Precondiciones El paciente debe estar afiliado a una EPS
Poscondiciones La historia es creada en el sistema y puede ser consultada por los diferentes usuarios autorizados
Nombre Consultar datos básicos del paciente
Descripción Representa el caso de uso por medio del cual el actor va a consultar los datos básicos de un paciente determinado.
Flujo de eventos Flujo Básico
El actor recibe la identificación del paciente, dicha identificación es el número de identificación del paciente que este registrado en el sistema de citas (cedula de ciudadanía, pasaporte, cedula de extranjería, etc.) y envía al sistema de historia clínicas la identificación del paciente
El sistema de historias clínicas valida la identificación y envía al sistema de citas los datos básicos.
Flujos Alternativos Historia no existe A partir del paso 1 del flujo básico, el sistema muestra un mensaje “La historia clínica asociada a la identificación ingresada no existe en el sistema” indicando que la historia clínica no existe.
Precondiciones El paciente debe estar registrado en el sistema de citas
Poscondiciones La historia clínica queda asignada a la cita respectiva.
Nombre Consultar historia
Descripción Representa el caso de uso por medio del cual el actor va a consultar la historia clínica de un paciente determinado.
Flujo de eventos Flujo Básico
El medico ingresa la identificación del paciente dicha
identificación es el número de identificación del paciente que este registrado en el sistema de citas (cedula de ciudadanía, pasaporte, cedula de extranjería, etc.)
El sistema valida la identificación y muestra la pantalla con la historia clínica.
Dicho formulario mostrará la siguiente información:
o Identificación: Este campo representa la identificación del
paciente (cedula de ciudadanía, pasaporte, cedula de extranjería, etc.)
o Nombre: Este campo representa el nombre completo del paciente
o Estatura: Este campo representa la estatura del paciente o Tipo de sangre: Este campo representa el tipo de sangre del
paciente o Ocupación: Este campo representa la ocupación actual del
paciente o Fecha de nacimiento: Este campo representa la fecha de
nacimiento del paciente o Dirección: Este campo representa la dirección actual del
paciente o Peso: Este campo representa el peso en kilogramos del
paciente o Lista de controles médicos: Lista de los controles médicos
llegado el caso de que los tuviere.
Flujos Alternativos historia no existe A partir del paso 1 del flujo básico, el sistema muestra un mensaje “La historia clínica asociada a la identificación suministrada no existe”, indicando al actor que la historia clínica no existe.
Precondiciones El paciente debe estar registrado en el sistema de citas
Nombre Consultar historia de citas del día
Descripción Representa el caso de uso por el medio del cual el actor va a consultar todas las historias clínicas de las citas que tiene programada para la fecha actual.
Flujo de eventos Flujo Básico
El medico ingresa su identificación, dicha identificación es el numero de identificación del medio (cedula de ciudadanía, pasaporte, cedula de extranjería, etc)
El sistema valida la identificación y le muestra el listado de las historias clínicas de la fecha actual
Flujos Alternativos Indentificacion medico no valida A partir del paso 1 del flujo básico, el sistema muestra un mensaje “La identificación no esta autorizada para realizar la consulta” indicando que el actor no esta autorizado para realizar la consulta.
Nombre CRUD Medicamentos
Descripción Este caso de uso describe los pasos que debe hacer el actor para consultar, crear, actualizar y/o borrar una formula medica en la historia clínica.
Flujo de eventos Flujo Básico
El sistema muestra la ventana de mantenimiento de medicamentos, dicha ventana le mostrara una lista con la información de todos los medicamentos, se le mostrara el código medicamento y nombre del medicamento.
El actor escoge la opción especifica (leer, consultar, insertar o eliminar).
El sistema le mostrara una ventana con la información del medicamento, dicha ventana tendrá el código y el nombre.
El actor realiza el proceso de mantenimiento1 del medicamento.
El sistema valida el resultado de la operación y termina el mantenimiento del medicamento, llevándolo a la ventana de mantenimiento de medicamentos.
Flujos Alternativos Operación invalida A partir del paso 4 del flujo básico, el sistema valida los datos mostrando un mensaje de error “La operación no se puede realizar debido a que existen datos invalidos” indicando al actor que existen datos invalidos y sigue mostrando la pantalla actual.
Precondiciones El paciente debe esta afiliado a una EPS
Poscondiciones La historia es actualizada en el sistema y puede ser consultada por los diferentes usuarios autorizados.
Nombre CRUD Procedimiento
Descripción Este caso de uso describe los pasos que debe hacer el actor para consultar, crear, actualizar y/o borrar un procedimiento en la historia clinica
Flujo de eventos Flujo Básico
El sistema muestra la ventana de mantenimiento del procedimiento, dicha ventana le mostrara una lista con la información de todos los procedimientos del sistema, se le mostrara el identificador y el nombre.
El actor escoge la opción especifica (leer, consultar, insertar o eliminar)
El sistema le mostrara una ventana con la información del procedimiento, dicha ventana tendrá la identificación y la descripción.
El actor realiza el proceso de mantenimiento2 del procedimiento
El sistema valida el resultado de la operación y termina el
1 EL proceso de mantenimiento se refiere a consultar, insertar, editar un determinado registro
mantenimiento del procedimiento, llevándolo a la ventana de mantenimiento de procedimientos.
Flujos Alternativos Operación invalida A partir del paso 4 del flujo básico, el sistema valida los datos
mostrando un mensaje de error “La operación no se puede realizar debido a que existen datos invalidos” indicando al actor que existen datos invalidos y sigue mostrando la pantalla actual.
Precondiciones El paciente debe esta afiliado a una EPS
Poscondiciones La historia es actualizada en el sistema y puede ser consultadpor los diferentes usuarios autorizados.
Nombre Registrar diagnostico actual
Descripción Este caso de uso describe los pasos que debe hacer el actor para registrar un diagnostico a la historia clínica del paciente determinado.
Flujo de eventos Flujo Básico
El sistema de citas solicita las historias clínicas de las citas de la fecha actural.
El sistema selecciona las historias de la fecha actual y las muestra como disponibles, mostrando una pantalla con la lista de las historias clínicas de la fecha actual.
Nombre Enviar citas de hoy
Descripción Este caso de uso describe los pasos que debe hacer el actor para enviar las historias clínicas de las citas programadas para la fecha actual.
Flujo de eventos Flujo Básico
El actor ingresa la identificación del paciente, dicha identificación es el número de identificación del paciente que está registrado en el sistema de citas (cedula de ciudadanía, pasaporte, cedula e extranjería, etc.).
El sistema valida la identificación y muestra la pantalla con la historia clínica actual
Dicho formulario mostrará la siguiente información:
o Identificación: Este campo representa la identificación del paciente (cedula de ciudadanía, pasaporte, cedula de extranjería, etc.)
o Nombre: Este campo representa el nombre completo del paciente
o Estatura: Este campo representa la estatura del paciente o Tipo de sangre: Este campo representa el tipo de sangre del
paciente o Ocupación: Este campo representa la ocupación actual del
paciente
o Fecha de nacimiento: Este campo representa la fecha de nacimiento del paciente
o Dirección: Este campo representa la dirección actual del paciente
o Peso: Este campo representa el peso en kilogramos del paciente
o Lista de controles médicos: Lista de los controles médicos llegado el caso de que los tuviere.
El actor ingresa el diagnostico
El sistema valida los datos y actualiza la historia clínica agregando el diagnostico y dando por terminado el proceso.
Flujos Alternativos Flujo alternativo historia no existe A partir del paso 1 del flujo básico, el sistema valida la identificación mostrando un mensaje ” La historia clínica asociada a la identificación suministrada no existe” indicando que la historia No existe
Flujo alternativo diagnostico inválido A partir del paso 3 del flujo básico, el sistema valida los datos mostrando un mensaje de error error “La operación no se puede realizar debido a que existen datos inválidos” indicándole al actor que existen datos inválidos y sigue mostrando la pantalla actual.
Precondiciones El paciente debe estar afiliado a una EPS
Poscondiciones La historia es actualizada en el sistema y puede ser consultada por los diferenrentes usuarios autorizados.
1. Diagrama de Clases
Nombre Paciente
Descripción Esta clase representa a un paciente que es un usuario del sistema, al cual se le van a asignar historias clínicas.
Atributos Identificación: Este campo representa la identificación del paciente Nombre: Este campo representa el nombre completo del paciente Estatura: Este campo representa la estatura del paciente Tipo de sangre: Este campo representa el tipo de sangre del paciente Ocupación: Este campo representa la ocupación actual del paciente Fecha de nacimiento: Este campo representa la fecha de nacimiento del paciente Dirección: Este campo representa la dirección actual del paciente Peso: Este campo representa el peso en kilogramos del paciente.
Metodos calcularEdad: Este método permite calcular la edad a partir de la fecha de nacimiento.
Nombre Historia clínica
Descripción Esta clase representa una historia clínica determinada, una historia clínica es un documento, el cual surge en el contacto entre el equipo de salud y los pacientes.
Atributos fechaCreacion: Este campo representa fecha de creación de la historia clínica
Nombre Control medico
Descripción Esta clase representa un control médico, un control médico es el registro de sintomatología y diagnostico del paciente
Atributos fechaControl: Este campo representa fecha del control medico
Nombre Formula medica
Descripción Esta clase representa una formula medica, Una formula medica es un documento en el cual está la lista de medicamentos asignados a un paciente según la sintomatología presentada
Atributos Id: Este campo representa el número de identificación de la formula medica, puede ser un consecutivo.
Nombre Procedimiento
Descripción Esta clase representa un procedimiento medico. Un procedimiento medico son las diferentes actividades que ofrece la entidad que pueden ser asignada según la sintamotologia por ejemplo una operación.
Atributos Identificación: Este campo representa la identificación interna del procedimiento. Descripción: Este campo representa la descripción breve del procedimiento
Nombre Medicamento
Descripción Esta clase representa un medicamento.
Atributos códigoMedicamento: Este campo representa la identificación interna del medicamento
nombreMedicamento: Este campo representa el nombre del medicamento.
Nombre Usuario
Descripción Esta clase representa al usuario del sistema de historias clínicas. Toda persona que va a hacer uso del sistema.
Atributos Identificación: Este campo representa la identificación del usuario Nombre: Este campo representa el nombre completo del usuario Usuario: Este campo representa el usuario con el cual va a hacer el proceso de login al sistema de historias clínicas Contraseña: Este campo representa la contraseña con el cual el usuario se va a identificar al momento de hacer login al sistema Estado: Este campo representa el estado del usuario en el sistema, con el cual se podrá hacer las respectivas validaciones de permisos para poder acceder al sistema. Perfil: Este campo representa los diferentes tipos de roles que puede tener el usuario, y con el cual el sistema de historias clínicas habilitar las respectivas operaciones que puede realizar.
Nombre Medico
Descripción Esta clase representa a un medico, y hereda todos los atributos de la clase usuario
Atributos Tarjeta profesional: Este campo representa la tarjeta profesional del medico. Especialización: Este campo representa la especialización del medico.
Nombre Cita
Descripción Esta clase representa a una cita, la cual es la reunión planeada entre un paciente y un medico, para realizar un diagnostico o un chequeo de la sintomatología presentada por el paciente.
Atributos FechaCita: Este campo representa la fecha de la cita LugarCita Este campo representa el lugar de la cita (sede, consultorio, etc.)
Nombre Controlador general
Descripción Esta clase representa al controlador, encargado de administrar las diferentes ventanas del sistema.
Nombre Controlador historia
Descripción Esta clase representa el controlador encargado de administrar toda la información de una historia clínica
Nombre Ventana validación informacion
Descripción Esta clase representa una ventana la cual está diseñada para recibir
la información del usuario.
Nombre Ventana Ingreso datos
Descripción Esta clase representa una ventana la cual está diseñada para manejar toda la información de las historias clínicas del paciente.
Nombre Ventana acerca de
Descripción Ventana donde se muestra los nombres de las personas desrrolladoras del sistema.
Nombre Ventana procedimiento
Descripción Ventana donde se muestra la informacion del procedimiento
Nombre Ventana Medicamento
Descripción Ventana donde se muestra la informacion del medicamento
Nombre Ventana Administracion de Historias
Descripción Ventana principal del sistema, en donde se muestran las diferentes opciones.
Nombre Ventana Controles medicos
Descripción Ventana donde se muetran los diferentes controles medicos asociados a una historia clínica
Nombre CRUD procedimientos
Descripción Ventana donde se muetran una lista con los procedimientos del sistema junto con las 4 opciones del CRUD
Nombre Control medicamentos
Descripción Esta clase representa el controlador encargado de administrar toda la información de una medicamento
Nombre Control procedimientos
Descripción Esta clase representa el controlador encargado de administrar toda la información de un procedimiento
Este es el frame principal de la aplicación, tiene las opciones de Registrar Paciente,
Modificar Paciente, Consultar Historia, Acerca de y Salir.
En “Registrar Paciente” sale un diálogo donde se digita la identificación de paciente
que vamos a registrar. Si le identificación ya existe saldrá un mensaje de información
“Historia Clinica Existente”.
El siguiente dialogo permite capturar los datos básicos del paciente.
La opción “Modificar Paciente” del Menu principal permite modificar los datos de un
paciente y revisar los controles médicos del mismo.
Prototipo de Software para gestión de Información de Matriculas y Pensiones de
Colegios Privados de Educación Media.
Diagrama de Clases.
Ingreso Al Sistema
Modulo Archivos
o Estudiante
o Docente
o Grupo
o Opciones de ordenamiento
o Opciones de búsqueda
o Dialogo para guardar y modificar.
o Mensajes de Información, Error y Confirmación.
o Calendario
Recommended