Mostrando entradas con la etiqueta Swing. Mostrar todas las entradas
Mostrando entradas con la etiqueta Swing. Mostrar todas las entradas

sábado, 3 de diciembre de 2011

Formularios en Java. Componentes (III)

Para ir terminando con los componentes de los formularios, o mejor dicho, para terminar de explicar tan sólo algunos de los más importantes y frecuentes, he hecho otro ejemplo, en el que aparecen fundamentalmente los siguientes componentes:
  • JMenu y JMenuItem
  • JToolBar
  • JFileChoser
  • JColorChoser
El ejemplo pretende ser un editor de texto, pero muy, muy sencillo, ya que la idea es ver la funcionalidad de los componentes anteriores. Las clases que he implementado han sido dos, una para el formulario (editor) y otra para el selector de color. A continuación dejo el código, así como unas capturas de pantalla de como ha quedado.

Los iconos de los botones los he cargado con una clase que nos había pasado el profesor con esta finalidad.

EDITOR

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

 private JTextArea texto;
 private JButton colorButton, negritaButton, cursivaButton;
 
 public EditorForm() {
  initForm();
  initComponents();
  setVisible(true);
 }

 private void initForm() {
  setTitle("Editor");
  setSize(640, 480);
  setResizable(false);
  setLocationRelativeTo(null);
  setDefaultCloseOperation(DISPOSE_ON_CLOSE);
 }

 private void initComponents() {
  crearMenu();
  crearBarraHerramientas();
  
  texto = new JTextArea();
  texto.setMargin(new Insets(10, 10, 10, 10));
  
  getContentPane().add(new JScrollPane(texto), BorderLayout.CENTER);
 }

 private void crearMenu() {
  JMenuItem nuevoMenuItem = new JMenuItem("Nuevo");
  nuevoMenuItem.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) { onNuevoMenuItemActionPerformed(e); }
  });
  JMenuItem guardarMenuItem = new JMenuItem("Guardar");
  JMenuItem guardarComoMenuItem = new JMenuItem("Guardar como...");
  guardarComoMenuItem.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) { onGuardarComoMenuItemActionPerformed(e); }
  });
  JMenuItem salirMenuItem = new JMenuItem("Salir");
  salirMenuItem.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) { onSalirMenuItemActionPerformed(e);
   }
  });
  
  JMenu archivoMenu = new JMenu("Archivo");
  archivoMenu.add(nuevoMenuItem);
  archivoMenu.addSeparator();
  archivoMenu.add(guardarMenuItem);
  archivoMenu.add(guardarComoMenuItem);
  archivoMenu.addSeparator();
  archivoMenu.add(salirMenuItem);
  
  JMenuBar barraMenu = new JMenuBar();
  barraMenu.add(archivoMenu);
  
  setJMenuBar(barraMenu);
 }

 protected void onNuevoMenuItemActionPerformed(ActionEvent e) {
  texto.setText("");
 }

 protected void onGuardarComoMenuItemActionPerformed(ActionEvent e) {
  JFileChooser guardarDialog = new JFileChooser();
  int resultado = guardarDialog.showSaveDialog(this);
  
  //Si la opción elegida ha sido "Guardar", le han dado a ese botón
  if (resultado == JFileChooser.APPROVE_OPTION) {
   //Donde se va a guardar
   File fichero = guardarDialog.getSelectedFile();

   //TODO Aquí implementaríamos el código necesario para guardar el texto
  }
 }

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

 private void crearBarraHerramientas() {
  colorButton = new JButton(Iconos.COLOR);
  colorButton.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) { onColorButtonActionPerformed(e); }
  });
  negritaButton = new JButton(Iconos.NEGRITA);
  negritaButton.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) { onNegritaButtonActionPerformed(e); }
  });
  cursivaButton = new JButton(Iconos.CURSIVA);
  cursivaButton.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) { onCursivaButtonActionPerformed(e); }
  });
  
  JToolBar barraHerramientas = new JToolBar();
  barraHerramientas.add(colorButton);
  barraHerramientas.add(negritaButton);
  barraHerramientas.add(cursivaButton);
  //Esta propiedad indica si el usuario puede mover la barra de herramientas o no
  barraHerramientas.setFloatable(false);
  barraHerramientas.setOrientation(JToolBar.HORIZONTAL);
  getContentPane().add(barraHerramientas, BorderLayout.NORTH);
 }

 protected void onColorButtonActionPerformed(ActionEvent e) {
  ColorDialog dialogo = new ColorDialog();
  dialogo.setVisible(true);
  texto.setForeground(dialogo.getColor());
  dialogo.dispose();
 }

 protected void onNegritaButtonActionPerformed(ActionEvent e) {
  // TODO Aquí implementaríamos la funcionalidad de este botón
 }

 protected void onCursivaButtonActionPerformed(ActionEvent e) {
  // TODO Aquí implementaríamos la funcionalidad de este botón
 }
 
}




SELECTOR DE COLOR

@SuppressWarnings("serial")
public class ColorDialog extends JDialog {
 
 private Color color;

 private JColorChooser colorChooser;
 private JButton seleccionarButton, cancelarButton;
 
 public ColorDialog() {
  initForm();
  initComponents();
 }

 private void initForm() {
  setTitle("Seleccionar color");
  setSize(450, 300);
  setDefaultCloseOperation(DISPOSE_ON_CLOSE);
  setLocationRelativeTo(null);
  setModal(true);
 }

 private void initComponents() {
  colorChooser = new JColorChooser();
  
  seleccionarButton = new JButton("Seleccionar");
  seleccionarButton.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) { onSeleccionarButtonActionPerformed(e); }
  });
  cancelarButton = new JButton("Cancelar");
  cancelarButton.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) { onCancelarButtonActionPerformed(e); }
  });
  
  JPanel botonesPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
  botonesPanel.add(seleccionarButton);
  botonesPanel.add(cancelarButton);
  
  getContentPane().add(colorChooser, BorderLayout.CENTER);
  getContentPane().add(botonesPanel, BorderLayout.SOUTH);
 }

 protected void onSeleccionarButtonActionPerformed(ActionEvent e) {
  this.color = colorChooser.getColor();
  //No hacemos dispose() porque tenemos que recuperar el color seleccionado
  setVisible(false);
 }

 protected void onCancelarButtonActionPerformed(ActionEvent e) {
  setVisible(false);
 }
 
 public Color getColor() {
  return color;
 }
 
}

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();
 }
}

martes, 22 de noviembre de 2011

Formularios en Java. Layout

En la entrada anterior puse un ejemplo del uso de varios componentes Swing que podemos usar en formularios. En ese ejemplo no utilicé ningún layout, por lo que para colocar los componentes donde queramos tenemos que hacerlo mediante coordenadas. Esto resulta bastante complicado, sobre todo a medida que aumenta la complejidad del formulario, por lo que se suele hacer es trabajar con layout.

Los layout indican la forma de organizar los componentes dentro de un contenedor. De manera que crearemos el contenedor, que puede ser un JPanel, JFrame, JDialog, etc., estableceremos el layout que más nos interese en cada caso y añadiremos los elementos

Algunos de los layout más importantes, de los que se muestra posteriormente un sencillo ejemplo de código y una imagen, son:
  • FlowLayout. Es el layout por defecto de los paneles (JPanel). En él los componentes se van añadiendo uno junto a otro en filas (de izquierda a derecha y de arriba a abajo). Se creará una nueva fila cuando sea necesario y se redistribuye el contenido al cambiar las dimensiones del contenedor.
  • BoxLayout. Organiza los componentes en una línea horizontal o vertical, sin dejar espacio entre ellos. Un ejemplo de su uso podría ser una barra de herramientas, donde hay varios botones uno junto a otro.
  • GridLayout. Este layout es similar a una tabla, ya que los elementos se distribuirán en sus celdas, que son de tamaño idéntico. Los elementos se añadirán a las celdas siguiendo el orden: de izquierda a derecha y de arriba a abajo.
  • GridBagLayout. Es el layout más complejo, pero también el más flexible. Coloca los componentes dentro de una rejilla, pero gracias al objeto "GridBagConstraints", el componente puede ocupar varias celdas, centrarse a uno u otro lado, que su columna sea más ancha, etc.
  • BorderLayout. Utiliza 5 áreas para colocar los componentes (norte, sur, este, oeste y centro), por lo que sólo se pueden añadir 5 componentes (si los componentes son paneles pueden tener a su vez varios componentes dentro).
Estos ejemplos sólo pretenden dar una noción de "cómo" son los distintos layout. Se han asignado los mismos a un JFrame y se les han añadido algunos componentes para hacerse una idea más fácil de cómo quedan. Normalmente en un formulario se utilizan distintos paneles (JPanel), cada uno con el layout más apropiado, y en ellos se distribuyen los componentes.

FLOWLAYOUT

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

 private JLabel unoLabel, dosLabel, tresLabel, cuatroLabel;
 
 public EjemploFlowLayout() {
  initForm();
  initComponents();
  setVisible(true);
 }

 private void initForm() {
  setTitle("Ejemplo de FlowLayout");
  setSize(400, 300);
  setLocationRelativeTo(null);
  setDefaultCloseOperation(DISPOSE_ON_CLOSE);
 }

 private void initComponents() {
  unoLabel = new JLabel("UNO");
  unoLabel.setOpaque(true);
  unoLabel.setBackground(Color.CYAN);
  dosLabel = new JLabel("DOS");
  dosLabel.setOpaque(true);
  dosLabel.setBackground(Color.RED);
  tresLabel = new JLabel("TRES");
  tresLabel.setOpaque(true);
  tresLabel.setBackground(Color.YELLOW);
  cuatroLabel = new JLabel("CUATRO");
  cuatroLabel.setOpaque(true);
  cuatroLabel.setBackground(Color.GREEN);
  
  //Añadimos el layout
  //Si en el constructor del FlowLayout no ponemos nada, los elementos se colocarán centrados
  getContentPane().setLayout(new FlowLayout(FlowLayout.RIGHT));
  getContentPane().add(unoLabel);
  getContentPane().add(dosLabel);
  getContentPane().add(tresLabel);
  getContentPane().add(cuatroLabel);
 }
}

En la imagen se puede apreciar la redistribución de los componentes:


BOXLAYOUT

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

 private JLabel unoLabel, dosLabel, tresLabel, cuatroLabel;
 
 public EjemploBoxLayout() {
  initForm();
  initComponents();
  setVisible(true);
 }

 private void initForm() {
  setTitle("Ejemplo de BoxLayout");
  setSize(400, 300);
  setLocationRelativeTo(null);
  setDefaultCloseOperation(DISPOSE_ON_CLOSE);
 }

 private void initComponents() {
  unoLabel = new JLabel("UNO");
  unoLabel.setOpaque(true);
  unoLabel.setBackground(Color.CYAN);
  dosLabel = new JLabel("DOS");
  dosLabel.setOpaque(true);
  dosLabel.setBackground(Color.RED);
  tresLabel = new JLabel("TRES");
  tresLabel.setOpaque(true);
  tresLabel.setBackground(Color.YELLOW);
  cuatroLabel = new JLabel("CUATRO");
  cuatroLabel.setOpaque(true);
  cuatroLabel.setBackground(Color.GREEN);
  
  //Añadimos el layout, en este caso los componentes seguirán el eje Y
  getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
  getContentPane().add(unoLabel);
  getContentPane().add(dosLabel);
  getContentPane().add(tresLabel);
  getContentPane().add(cuatroLabel);
 }
}


GRIDLAYOUT

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

 private JLabel unoLabel, dosLabel, tresLabel, cuatroLabel;
 
 public EjemploGridLayout() {
  initForm();
  initComponents();
  setVisible(true);
 }

 private void initForm() {
  setTitle("Ejemplo de GridLayout");
  setSize(400, 300);
  setLocationRelativeTo(null);
  setDefaultCloseOperation(DISPOSE_ON_CLOSE);
 }

 private void initComponents() {
  unoLabel = new JLabel("UNO");
  unoLabel.setOpaque(true);
  unoLabel.setBackground(Color.CYAN);
  dosLabel = new JLabel("DOS");
  dosLabel.setOpaque(true);
  dosLabel.setBackground(Color.RED);
  tresLabel = new JLabel("TRES");
  tresLabel.setOpaque(true);
  tresLabel.setBackground(Color.YELLOW);
  cuatroLabel = new JLabel("CUATRO");
  cuatroLabel.setOpaque(true);
  cuatroLabel.setBackground(Color.GREEN);
  
  //Añadimos el layout
  //En el constructor he indicado el número de filas y columnas
  //Si el número de filas es 0, se irán creando a medida que se añaden elementos
  getContentPane().setLayout(new GridLayout(2, 2));
  getContentPane().add(unoLabel);
  getContentPane().add(dosLabel);
  getContentPane().add(tresLabel);
  getContentPane().add(cuatroLabel);
 }
}


GRIDBAGLAYOUT

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

 private JLabel unoLabel, dosLabel, tresLabel;
 
 public EjemploGridBagLayout() {
  initForm();
  initComponents();
  setVisible(true);
 }

 private void initForm() {
  setTitle("Ejemplo de GridBagLayout");
  setSize(400, 300);
  setLocationRelativeTo(null);
  setDefaultCloseOperation(DISPOSE_ON_CLOSE);
 }

 private void initComponents() {
  unoLabel = new JLabel("UNO");
  unoLabel.setOpaque(true);
  unoLabel.setBackground(Color.CYAN);
  dosLabel = new JLabel("DOS");
  dosLabel.setOpaque(true);
  dosLabel.setBackground(Color.RED);
  tresLabel = new JLabel("TRES");
  tresLabel.setOpaque(true);
  tresLabel.setBackground(Color.YELLOW);
  
  //Creamos la constraint para el primer elemento
  GridBagConstraints constraint = new GridBagConstraints();
  //Coordenadas, celda en la que se colocará el componente "unoLabel"
  constraint.gridx = 0;
  constraint.gridy = 0;
  //Número de celdas que ocupa a lo ancho y a lo alto
  constraint.gridwidth = 1;
  constraint.gridheight = 1;
  //Peso. Cuando los componentes no ocupan todo el espacio, el espacio sobrante se reparte
  //Si lo ponemos a cero cada componente cogerá lo que necesite
  //En este caso se extiende a lo ancho
  constraint.weightx = 1.0;
  constraint.weighty = 0.0;
  //Anclaje. Posición en la que se coloca el componente dentro de la propia celda. Depende del fill
  constraint.anchor = GridBagConstraints.CENTER;
  //Cómo se coloca el componente dentro de la celda. Both (se estira en todo su espacio), Vertical, Horizontal
  constraint.fill = GridBagConstraints.BOTH;
  //Margen con los bordes de la celda
  constraint.insets = new Insets(5, 5, 5, 5);
  
  //Añadimos el layout
  getContentPane().setLayout(new GridBagLayout());
  getContentPane().add(unoLabel, constraint);
  //Con otro de los constructores de la clase GridBagConstraints, podemos instanciarla directamente
  //al añadir el elemento:
  getContentPane().add(dosLabel, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHEAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
  //El tercer componente ocupa dos celdas y se extiende a lo alto
  getContentPane().add(tresLabel, new GridBagConstraints(0, 1, 2, 1, 0.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
 }
 
}


BORDERLAYOUT

@SuppressWarnings("serial")
public class EjemploBorderLayout extends JFrame {
 
 private JLabel norteLabel, surLabel, esteLabel, oesteLabel, centroLabel;
 
 public EjemploBorderLayout() {
  initForm();
  initComponents();
  setVisible(true);
 }

 private void initForm() {
  setTitle("Ejemplo de BorderLayout");
  setSize(400, 300);
  setLocationRelativeTo(null);
  setDefaultCloseOperation(DISPOSE_ON_CLOSE);
 }

 private void initComponents() {
  norteLabel = new JLabel("NORTE");
  norteLabel.setOpaque(true);
  norteLabel.setBackground(Color.CYAN);
  norteLabel.setHorizontalAlignment(JLabel.CENTER);
  surLabel = new JLabel("SUR");
  surLabel.setOpaque(true);
  surLabel.setBackground(Color.RED);
  surLabel.setHorizontalAlignment(JLabel.CENTER);
  esteLabel = new JLabel("ESTE");
  esteLabel.setOpaque(true);
  esteLabel.setBackground(Color.YELLOW);
  oesteLabel = new JLabel("OESTE");
  oesteLabel.setOpaque(true);
  oesteLabel.setBackground(Color.GREEN);
  centroLabel = new JLabel("CENTRO");
  centroLabel.setOpaque(true);
  centroLabel.setBackground(Color.WHITE);
  centroLabel.setHorizontalAlignment(JLabel.CENTER);
  centroLabel.setVerticalAlignment(JLabel.CENTER);
  
  //Este paso no sería necesario, ya que por defecto, los JFrame tienen este layout
  getContentPane().setLayout(new BorderLayout());
  //Añadimos los elementos indicando en que posición
  getContentPane().add(norteLabel, BorderLayout.NORTH);
  getContentPane().add(surLabel, BorderLayout.SOUTH);
  getContentPane().add(esteLabel, BorderLayout.EAST);
  getContentPane().add(oesteLabel, BorderLayout.WEST);
  //Lo que se añade en el centro ocupará el mayor espacio posible
  //Deja al resto sólo lo que necesitan.
  getContentPane().add(centroLabel, BorderLayout.CENTER);
 }

}

lunes, 21 de noviembre de 2011

Formularios en Java. Componentes (I)

En esta entrada os dejo un sencillo ejemplo del uso de varios componentes Swing que podemos añadir a nuestros formularios. Los componentes usados son:
  • JButton.
  • JLabel.
  • JTextField.
  • JPasswordField.
He usado los métodos más comunes de estos componentes, tienen mucho más, así que si quieres hacer algo en particular, simplemente hay que investigar un poco a ver si se puede con todas las opciones que ofrecen. Además, en este ejemplo no he trabajado con "Layouts" (hablaré brevemente de ellos y pondré ejemplos de varios en la próxima entrada), sino que los componentes se han colocado en el formulario mediante coordenadas.

@SuppressWarnings("serial")
public class ComponentesFormI extends JFrame {
 
 //Componentes del formulario
 private JButton cerrarButton, activarButton;
 private JLabel nombreLabel, passwordLabel;
 private JTextField nombreText;
 private JPasswordField password;
 
 public ComponentesFormI() {
  initForm();
  initComponents();
  setVisible(true);
 }

 private void initForm() {
  setTitle("Componentes de los formularios (I)");
  setSize(640, 480);
  setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
  addWindowListener(new WindowAdapter() {
   //Cuando se "cierre", se ejecutará el método onWindowClosing(e)
   public void windowClosing(WindowEvent e) { onWindowClosing(e); }
  });
  setLocationRelativeTo(null);
  //Para que no se pueda redimensionar
  setResizable(false);
 }

 private void initComponents() {
  cerrarButton = new JButton("Cerrar");
  //Indicamos las coordenadas y las dimensiones del componente
  //Cuando veamos los layouts no será necesario indicar las coordenadas
  cerrarButton.setBounds(500, 380, 100, 30);
  cerrarButton.setToolTipText("Al pulsarlo, se da la opción de cerrar el formulario.");
  //Especificamos la tecla que puede activar este botón: Alt + C
  cerrarButton.setMnemonic(KeyEvent.VK_C);
  cerrarButton.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) { onCerrarButtonActionPerformed(e); }
  });
  
  activarButton = new JButton("Activar");
  activarButton.setBounds(250, 135, 100, 30);
  activarButton.setToolTipText("Al pulsarlo, activa los cuadros de texto.");
  activarButton.setMnemonic(KeyEvent.VK_A);
  activarButton.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) { onActivarButtonActionPerformed(e); }
  });
  
  nombreLabel = new JLabel("Nombre:");
  nombreLabel.setBounds(50, 50, 150, 50);
  //Para que se vea el color de fondo
  nombreLabel.setOpaque(true);
  nombreLabel.setBackground(Color.MAGENTA);
  nombreLabel.setVerticalAlignment(JLabel.CENTER);
  nombreLabel.setHorizontalAlignment(JLabel.CENTER);
  
  passwordLabel = new JLabel("Contraseña:");
  passwordLabel.setBounds(50, 200, 150, 50);
  passwordLabel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
  passwordLabel.setVerticalAlignment(JLabel.TOP);
  passwordLabel.setHorizontalAlignment(JLabel.CENTER);
  
  nombreText = new JTextField();
  nombreText.setText("Pulsa el botón \"Activar\" para escribir tu nombre y contraseña.");
  nombreText.setBounds(250, 50, 350, 50);
  nombreText.setEditable(false);
  
  password = new JPasswordField();
  password.setBounds(250, 200, 350, 50);
  password.setEditable(false);
  
  //Los JFrame tienen por defecto el BorderLayout, se lo quitamos para añadir los componentes
  //y que estos se muestren en las coordenadas que hemos indicado
  getContentPane().setLayout(null);
  //Añadimos todos los componentes al formulario
  getContentPane().add(cerrarButton);
  getContentPane().add(activarButton);
  getContentPane().add(nombreLabel);
  getContentPane().add(passwordLabel);
  getContentPane().add(nombreText);
  getContentPane().add(password);
 }

 protected void onActivarButtonActionPerformed(ActionEvent e) {
  nombreText.setEditable(true);
  nombreText.requestFocus();
  nombreText.selectAll();
  password.setEditable(true);
 }

 protected void onCerrarButtonActionPerformed(ActionEvent e) {
  cerrar();
 }

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

 private void cerrar() {
  //Cuadro de diálogo para preguntar al usuario si desea salir
  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();
  }
 }

}

Y... ¡tachán! Así es como ha quedado el formulario:


Después de pulsar el botón "Activar":

domingo, 20 de noviembre de 2011

Formularios en Java

El tema de los formularios da para mucho. Intentaré resumirlo un poco mediante ejemplos de los distintos componentes que se pueden utilizar en los mismos y cómo podemos utilizarlos.

En esta entrada me centraré en algunas de las distintas opciones que tenemos para implementar la interfaz gráfica. Estas opciones las encontramos en el paquete javax.swing y son:
  • JWindow. Ventana sin barra de título ni botones para cerrar, maximizar, etc. Es la típica ventana que encontramos muchas veces al iniciar un programa, mientras este se está cargando.
  • JFrame. Ventana con barra de título y botones.
  • JDialog. Cuadro de diálogo, que sólo tiene el botón de cerrar.
A continuación dejo un ejemplo de código de cada una de ellas, junto con una captura de pantalla del resultado final y un ejemplo real del que podría ser su uso.

JWINDOW

@SuppressWarnings("serial")
public class EjemploJWindow extends JWindow {
 
 public EjemploJWindow() {
  initForm();
  initComponents();
  setVisible(true);
 }

 private void initForm() {
  setSize(400, 300);
  getContentPane().setBackground(Color.PINK);
  setLocationRelativeTo(null);
 }

 private void initComponents() {
  // Aquí se inicializarían los componentes de la ventana.
 }

}


Aunque parezca un rectángulo rosa hecho en el Paint, es el resultado de ejecutar el código anterior. Ahí va un ejemplo de lo que se podría hacer con JWindow, la pantalla de inicio de un programa:


JFRAME

@SuppressWarnings("serial")
public class EjemploJFrame extends JFrame {
 
 public EjemploJFrame() {
  initForm();
  initComponents();
  setVisible(true);
 }

 //Método en el que se inicializa el formulario
 private void initForm() {
  setTitle("Ejemplo de JFrame");
  setSize(400, 300);
  //Al indicar "null", el formulario aparecerá en el centro de la pantalla.
  setLocationRelativeTo(null);
  //Especificamos la operación que ocurrirá por defecto cuando se "cierre" el formulario.
  //En este caso, se cerrará
  setDefaultCloseOperation(DISPOSE_ON_CLOSE);
 }

 //Método en el que se inicializan los componentes del formulario
 private void initComponents() {
  // Aquí inicializaremos todos los componentes que tenga nuestro formulario.  
 }

}



JDIALOG

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

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

 private void initForm() {
  setTitle("Ejemplo de JDialog");
  setSize(400, 300);
  setLocationRelativeTo(null);
  setDefaultCloseOperation(DISPOSE_ON_CLOSE);
  //Esta opción hace que se bloque la ventana desde donde se invoca al cuadro de diálogo
  //Para que no esté disponible hasta que se haga algo en éste
  setModal(true);
 }

 private void initComponents() {
  //Aquí inicializaremos todos los componentes que tenga nuestro cuadro de diálogo.
 }
}