martes, 29 de noviembre de 2011

Formularios en Java. Componentes (II)

Continúo con ejemplos de componentes Swing para formularios. Para realizar estos ejemplos, he implementado un sencillo formulario que nos permita "gestionar" nuestros hobbies, por ejemplo, que nos permita ver el listado de libros que tenemos, añadir alguno nuevo, etc.

Los nuevos componentes utilizados han sido:
  • JTable. A su vez utiliza una clase que implementa TableModel.
  • JTabbedPane
  • JOptionPane
  • JCheckBox
  • JComboBox<E>
  • JTextArea
  • JRadioButton y ButtonGroup
Además, he utilizado algunos de los layouts vistos anteriormente, lo que le da mucho mejor aspecto a los fomrularios, sin necesidad de estar cuadrando coordenadas.

FORMULARIO INICIAL
Es el que se muestra al abrir la aplicación. Consiste en un panel con varias pestañas para cada uno de los hobbies que queramos gestionar. En la primera, se muestra un listado de libros.
Si hacemos clic en "Salir", se muestra un cuadro de diálogo creado con la clase JOptionPane, tal y como se puede ver en el código.

@SuppressWarnings("serial")
public class ComponentesFormII extends JFrame {

 JButton salirButton, nuevoDiscoButton, nuevoLibroButton;
 JTable discosTable, librosTable;
 LibrosTableModel librosTableModel;
 
 public ComponentesFormII() {
  initForm();
  initComponents();
  setVisible(true);
 }

 private void initForm() {
  setTitle("Mis hobbies");
  setSize(640, 480);
  setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
  addWindowListener(new WindowAdapter() {
   public void windowClosing(WindowEvent e) { onWindowClosing(e); }
  });
  setLocationRelativeTo(null);
 }

 private void initComponents() {
  salirButton = new JButton("Salir");
  salirButton.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) { onSalirButtonActionPerformed(e); }
  });
  salirButton.setMnemonic(KeyEvent.VK_S);
  
  JPanel botonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
  botonPanel.add(salirButton);
  
  JTabbedPane hobbiesPanel = new JTabbedPane();
  hobbiesPanel.add("Libros", librosPanel());
  //Paneles vacíos
  hobbiesPanel.add("Música", new JPanel());
  hobbiesPanel.add("Viajes", new JPanel());
  
  getContentPane().add(hobbiesPanel, BorderLayout.CENTER);
  getContentPane().add(botonPanel, BorderLayout.SOUTH);
 }

 protected void onWindowClosing(WindowEvent e) {
  salir();
 }

 protected void onSalirButtonActionPerformed(ActionEvent e) {
  salir();
 }

 private void salir() {
  BaseDatos.desconectar();
  //La clase JOptionPane nos permite mostrar diferentes cuadros de diálogo
  //Estableciendo las opciones en el constructor
  int respuesta = JOptionPane.showConfirmDialog(this, "¿Está seguro de que quiere salir?", "Salir", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
  if (respuesta == JOptionPane.YES_OPTION) {
   dispose();
  }
 }
 
 private JPanel librosPanel() {
  nuevoLibroButton = new JButton("Añadir libro");
  nuevoLibroButton.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) { onNuevoLibroButtonActionPerformed(e); }
  });
  nuevoLibroButton.setMnemonic(KeyEvent.VK_L);
  
  JPanel botonPanel = new JPanel();
  botonPanel.add(nuevoLibroButton);
  
  librosTableModel = new LibrosTableModel();
  librosTable = new JTable(librosTableModel);
  
  JPanel tablaPanel = new JPanel(new BorderLayout());
  tablaPanel.setBorder(BorderFactory.createTitledBorder(" Libros: "));
  //Debemos poner la tabla dentro de un panel de tipo JScrollPane
  //Para que se muestre correctamente
  tablaPanel.add(new JScrollPane(librosTable), BorderLayout.CENTER);
  tablaPanel.add(botonPanel, BorderLayout.SOUTH);
  
  return tablaPanel;
 }

 protected void onNuevoLibroButtonActionPerformed(ActionEvent e) {
  new LibrosForm();
  librosTableModel.refrescar();
 }
 
 
}

LibrosTableModel

public class LibrosTableModel implements TableModel {

 Hobbies hobbies;
 List<Libro> libros;
 private TableModelListener listener;
 
 public LibrosTableModel() {
  hobbies = new Hobbies();
  libros = hobbies.recuperarLibros();
 }
 
 @Override
 public void addTableModelListener(TableModelListener arg0) {
  listener = arg0;
 }

 @Override
 public Class<?> getColumnClass(int arg0) {
  switch (arg0) {
   case 0: return Long.class;
   case 1: return String.class;
   case 2: return Boolean.class;
   case 3: return Boolean.class;
   case 4: return String.class;
  }
  return null;
 }

 @Override
 public int getColumnCount() {
  return 5;
 }

 @Override
 public String getColumnName(int arg0) {
  switch (arg0) {
   case 0: return "ISBN";
   case 1: return "Título";
   case 2: return "Leído";
   case 3: return "Lo tengo";
   case 4: return "Autor";
  }
  return null;
 }

 @Override
 public int getRowCount() {
  return libros.size();
 }

 @Override
 public Object getValueAt(int arg0, int arg1) {
  Libro libro = libros.get(arg0);
  switch (arg1) {
   case 0: return libro.getIsbn();
   case 1: return libro.getTitulo();
   case 2: return libro.getLeido();
   case 3: return libro.getTengo();
   case 4: return libro.getAutor().getNombre();
  }
  return null;
 }

 @Override
 public boolean isCellEditable(int arg0, int arg1) {
  return false;
 }

 @Override
 public void removeTableModelListener(TableModelListener arg0) {
  // TODO Auto-generated method stub

 }

 @Override
 public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
  // TODO Auto-generated method stub

 }
 
 //Método que nos permite actualizar el listado de libros cuando hemos añadido alguno
 public void refrescar() {
  libros = hobbies.recuperarLibros();
  listener.tableChanged(new TableModelEvent(this));
 }

}


JOPTIONPANE


CUADRO DE DIÁLOGO "CREAR LIBRO"
Si en el formulario anterior hacemos clic sobre "Añadir libro", se abre un cuadro de diálogo en el que podremos indicar los diferentes datos del ejemplar que queramos. Además, si en el JComboBox, no está el autor que queremos, podemos hacer clic en "Nuevo autor" para añadirlo.

@SuppressWarnings("serial")
public class LibrosForm extends JDialog {

 private JButton guardarButton, cancelarButton, nuevoAutorButton;
 private JLabel isbnLabel, tituloLabel, autorLabel, sinopsisLabel, generoLabel;
 private JTextField isbnText, tituloText;
 private JCheckBox leidoCheck, tengoCheck;
 private JComboBox<String> autores;
 private JTextArea sinopsisTextArea;
 private JRadioButton terrorRadio, cienciaFiccionRadio, romanceRadio, fantasiaRadio;
 private ButtonGroup generoGroup;
 
 private Hobbies hobbies;
 private List<Autor> listado;
 
 public LibrosForm() {
  hobbies = new Hobbies();
  listado = hobbies.recuperarAutores();
  initForm();
  initComponents();
  setVisible(true);
 }

 private void initForm() {
  setTitle("Crear libro");
  setSize(480, 400);
  setLocationRelativeTo(null);
  setDefaultCloseOperation(DISPOSE_ON_CLOSE);
  setResizable(false);
  setModal(true);
 }

 private void initComponents() {
  guardarButton = new JButton("Guardar");
  guardarButton.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) { onGuardarButtonActionPerformed(e); }
  });
  cancelarButton = new JButton("Cancelar");
  cancelarButton.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) { onCancelarButtonActionPerformed(e); }
  });
  nuevoAutorButton = new JButton("Nuevo autor");
  nuevoAutorButton.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) { onNuevoAutorButtonActionPerformed(e); }
  });
  isbnLabel = new JLabel("ISBN:");
  tituloLabel = new JLabel("Título:");
  autorLabel = new JLabel("Autor:");
  sinopsisLabel = new JLabel("Sinopsis:");
  sinopsisLabel.setVerticalAlignment(JLabel.TOP);
  generoLabel = new JLabel("Género:");
  generoLabel.setVerticalAlignment(JLabel.TOP);
  isbnText = new JTextField();
  tituloText = new JTextField();
  sinopsisTextArea = new JTextArea();
  //Debemos indicar el número de filas que queremos que tenga el JTextArea
  sinopsisTextArea.setRows(3);
  leidoCheck = new JCheckBox("Leído");
  tengoCheck = new JCheckBox("Lo tengo");
  terrorRadio  = new JRadioButton("Terror");
  //El método setActionCommand(), nos permite saber a través del JButtonGroup, cuál es el elemento seleccionado
  terrorRadio.setActionCommand("Terror");
  cienciaFiccionRadio = new JRadioButton("Ciencia ficción");
  cienciaFiccionRadio.setActionCommand("Ciencia ficción");
  romanceRadio = new JRadioButton("Romance");
  romanceRadio.setActionCommand("Romance");
  fantasiaRadio = new JRadioButton("Fantasía");
  fantasiaRadio.setActionCommand("Fantasía");
  //El ButtonGroup realiza una agrupación lógica de los JRadioButton, que permite saber cuál es el seleccionado
  generoGroup = new ButtonGroup();
  generoGroup.add(terrorRadio);
  generoGroup.add(cienciaFiccionRadio);
  generoGroup.add(romanceRadio);
  generoGroup.add(fantasiaRadio);
  autores = new JComboBox<String>();
  
  for (Autor autor : listado) {
   autores.addItem(autor.getNombre());
  }
  
  JPanel botonesPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
  botonesPanel.add(guardarButton);
  botonesPanel.add(cancelarButton);
  
  //Ponemos el JTextArea dentro de un JScrollPane, para que podamos ver todas las filas si se escribe más de las indicadas
  JScrollPane sinopsisPanel = new JScrollPane(sinopsisTextArea);
  
  JPanel checkPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
  checkPanel.add(leidoCheck);
  checkPanel.add(tengoCheck);
  
  JPanel generoPanel = new JPanel(new GridLayout(2, 2));
  generoPanel.add(terrorRadio);
  generoPanel.add(cienciaFiccionRadio);
  generoPanel.add(romanceRadio);
  generoPanel.add(fantasiaRadio);
  
  JPanel datosPanel = new JPanel(new GridBagLayout());
  datosPanel.add(isbnLabel, new GridBagConstraints(0, 0, 1, 1, 0.25, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
  datosPanel.add(isbnText, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
  datosPanel.add(tituloLabel, new GridBagConstraints(0, 1, 1, 1, 0.25, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
  datosPanel.add(tituloText, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
  datosPanel.add(autorLabel, new GridBagConstraints(0, 2, 1, 1, 0.25, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
  datosPanel.add(autores, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
  datosPanel.add(nuevoAutorButton, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
  datosPanel.add(sinopsisLabel, new GridBagConstraints(0, 4, 1, 1, 0.25, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
  datosPanel.add(sinopsisPanel, new GridBagConstraints(1, 4, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
  datosPanel.add(generoLabel, new GridBagConstraints(0, 5, 1, 1, 0.25, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
  datosPanel.add(generoPanel, new GridBagConstraints(1, 5, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
  datosPanel.add(checkPanel, new GridBagConstraints(1, 6, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
  
  getContentPane().setLayout(new BorderLayout());
  getContentPane().add(datosPanel, BorderLayout.NORTH);
  getContentPane().add(botonesPanel, BorderLayout.SOUTH);
 }

 protected void onGuardarButtonActionPerformed(ActionEvent e) {
  Libro libro = new Libro();
  libro.setIsbn(Long.parseLong(isbnText.getText()));
  libro.setTitulo(tituloText.getText());
  libro.setLeido(leidoCheck.isSelected());
  libro.setTengo(tengoCheck.isSelected());
  libro.setAutor(listado.get(autores.getSelectedIndex()));
  libro.setGenero(generoGroup.getSelection().getActionCommand());
  libro.setSinopsis(sinopsisTextArea.getText());
  
  hobbies.insertarLibro(libro);
  dispose();
 }

 protected void onCancelarButtonActionPerformed(ActionEvent e) {
  dispose();
 }

 protected void onNuevoAutorButtonActionPerformed(ActionEvent e) {
  new AutorForm();
  
  //Para actualizar el listado de autores, eliminamos primero todos los elementos
  autores.removeAllItems();
  //Y los volvemos a añadir (así estará el que se acaba de añadir)
  listado = hobbies.recuperarAutores();
  for (Autor autor : listado) {
   autores.addItem(autor.getNombre());
  }
  //Para que aparezca seleccionado el autor que acabamos de añadir
  autores.setSelectedIndex(listado.size()-1);
 }
}


CUADRO DE DIÁLOGO "NUEVO AUTOR"

@SuppressWarnings("serial")
public class AutorForm extends JDialog {
 
 private JButton guardarButton, cancelarButton;
 private JLabel nombreLabel;
 private JTextField nombreText;

 public AutorForm() {
  initForm();
  initComponents();
  setVisible(true);
 }

 private void initForm() {
  setTitle("Nuevo autor");
  setSize(350, 100);
  setDefaultCloseOperation(DISPOSE_ON_CLOSE);
  setLocationRelativeTo(null);
  setResizable(false);
  setModal(true);
 }

 private void initComponents() {
  guardarButton = new JButton("Guardar");
  guardarButton.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) { onGuardarButtonActionPerformed(e); }
  });
  cancelarButton = new JButton("Cancelar");
  cancelarButton.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) { onCancelarButtonActionPerformed(e); }
  });
  nombreLabel = new JLabel("Nombre:");
  nombreText = new JTextField();
  
  JPanel botonesPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
  botonesPanel.add(guardarButton);
  botonesPanel.add(cancelarButton);
  
  JPanel datosPanel = new JPanel(new GridBagLayout());
  datosPanel.add(nombreLabel, new GridBagConstraints(0, 0, 1, 1, 0.1, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
  datosPanel.add(nombreText, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
  
  getContentPane().setLayout(new BorderLayout());
  getContentPane().add(datosPanel, BorderLayout.NORTH);
  getContentPane().add(botonesPanel, BorderLayout.SOUTH);
 }

 protected void onGuardarButtonActionPerformed(ActionEvent e) {
  Hobbies hobbies = new Hobbies();
  Autor autor = new Autor();
  autor.setNombre(nombreText.getText());
  
  hobbies.insertarAutor(autor);
  dispose();
 }

 protected void onCancelarButtonActionPerformed(ActionEvent e) {
  dispose();
 }
}

5 comentarios: