jueves, 22 de diciembre de 2011

Feliz Navidad

0
01
110
00101
0001110
110100110
00110100111
10011101101011
1110101011101011
100111010100100101
10101000101001011011
1111010010001111010111
010001010010101000111001
00011101010100010111010101
001
100
010

¡Y PRÓSPERO 2012!

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.
 }
}


lunes, 14 de noviembre de 2011

Acceso a bases de datos SQL Server

Para acceder a bases de datos SQL Server, simplemente tenemos que instalar el correspondiente driver JDBC y modificar el fichero de configuración del acceso a bases de datos, por lo que resulta bastante más sencillo que en el caso de bases de datos Access (puente JDBC-ODBC).

El driver (sqljdbc4.jar) lo encontrarás en este enlace: Controlador JDBC de Microsoft SQL Server. Os recomiendo descargar el archivo .tar.gz, dentro de él está el driver sqljdbc4.jar.

Cuando te lo has descargado, simplemente debes incluirlo en todos los proyectos en los que vayas a acceder a una base de datos SQL Server. Lo puedes copiar directamente dentro del directorio del proyecto en Eclipse.


Una vez copiado, debes añadirlo a las librerías, para ello: clic con el botón derecho del ratón sobre el .jar, vamos a Build Path > Add to Build Path

Además, debes modificar el fichero de configuración, que quedará de la siguiente manera:

# Fichero de propiedades para el acceso a la base de datos

# Driver de la base de datos:
db.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver

# Url de conexión:
db.url=jdbc:sqlserver://localhost:1433;databaseName=faltometro

# Usuario y contraseña de SQL Server:
db.username=sa
db.password=1234

Nosotros hemos utilizado el inicio de sesión de SQL Server "sa", que es el usuario administrador del sistema.

PROBLEMAS

En clase surgieron varios problemas a la hora de conectar a la base de datos, ya que no reconocía el usuario que habíamos indicado. Ahí van los pasos que seguimos para solucionarlo:

** En SQL Server, activamos el usuario "sa" y le damos contraseña. Lo puedes hacer fácilmente ejecutando la siguiente consulta:

alter login sa enable;
go
alter login sa with password='1234';
go

** En las propiedades del servidor, debemos indicar que la autenticación sea tanto de Windows como de SQL Server (ventana Seguridad).

** También detuvimos el servicio SQL Express, en el Administrador de Configuración de SQL Server.

domingo, 6 de noviembre de 2011

Instalar documentación de Java en Eclipse

En esta entrada explicaré como instalar la documentación de Java en Eclipse. A mí me resulta bastante útil tener toda la documentación instalada, ya que muchas veces trabajo sin estar conectada a internet y aunque este conectada, es mucho más inmediato de esta manera.

En primer lugar, hay que descargarse la documentación (para Java 7) en el siguiente enlace:

Guardas el archivo donde tú quieras, yo lo guardé en la misma carpeta donde está el workspace, así están todas las cosas de Eclipse en el mismo directorio.

Ahora pasamos al Eclipse, vamos al menú "Window" y dentro elegimos "Preferences".

En el cuadro de diálogo que se abre, vamos a Java > Installed JREs (nos tenemos que haber bajado la documentación para alguna de las JREs que tenemos instalada. Elegimos la que nos interese y la editamos.


En el listado de librerías, buscamos rt.jar y hacemos clic en el botón de la derecha "Javadoc Location...", para elegir la ruta del fichero que nos hemos descargado previamente.


Elegimos la opción de "Javadoc in archive", buscamos la ruta donde hemos guardado el archivo con la documentación y hacemos clic en "OK".


Ya tenemos nuestra documentación instalada y lista para usar en cualquier momento. Si tenemos dudas sobre algún método, clase, etc y queremos ver más información basta con pararte con el ratón sobre él o bien hacer clic sobre el elemento en cuestión y elegir la pestaña "Javadoc":



Espero que esta entrada os resulte útil.

Ejercicio "Efemérides" (base de datos)

Crear una aplicación que permita gestionar una base de datos de efemérides. Todas las operaciones se realizarán mediante consola, ya que el tema de formularios lo hemos empezado a ver después del de acceso a bases de datos.

Para empezar creamos en Access la base de datos "efemerides", que contendrá una única entidad: "efemeride", con los siguientes atributos:
  • id. De tipo entero.
  • texto. De tipo texto.
  • fecha. De tipo fecha.
Una vez creada la base de datos, implementamos el puente JDBC-ODBC y empezamos a trabajar.

Dentro de nuestro proyecto, crearemos la clase "BaseDatos" y el fichero de configuración, que como vimos en la entrada anterior nos facilitan todas las gestiones que realicemos con respecto al acceso a bases de datos.

Además, para que todo sea más realista y más sencillo de entender para el programador, crearemos la clase "Efemeride", que tendrá los atributos propios de una efeméride y, como métodos, los correspondientes "getters" y "setters".

CLASE EFEMERIDE

public class Efemeride {
 private Integer id;
 private String texto;
 private Date fecha;

 public Integer getId() {
  return id;
 }

 public void setId(Integer id) {
  this.id = id;
 }

 public String getTexto() {
  return texto;
 }

 public void setTexto(String texto) {
  this.texto = texto;
 }

 public Date getFecha() {
  return fecha;
 }

 public void setFecha(Date fecha) {
  this.fecha = fecha;
 }
}

TRUCO: una vez que has especificado todos los atributos de una clase, en Eclipse es muy sencillo generar los métodos getAtributo() y setAtributo(Dato dato). Sólo tienes que hacer clic con el botón derecho y en "Source" elegir "Generate Getters and Setters". En el cuadro de diálogo que se abre eliges los atributos de los que quieres generar estos métodos, haces clic en "OK" y ¡listo!

Para controlar las excepciones de nuestra aplicación, crearemos nuestra propia excepción. En nuestro caso esta clase fue facilitada por el profesor, así como una interfaz ("IEfemerides") que debe implementar la clase "Efemerides". Esta clase es la encargada de realizar todas las gestiones con la base de datos (insertar datos, actualizar, recuperar, etc.).

CLASE EFEMERIDEEXCEPTION

public class EfemerideException extends Exception {
 private static final long serialVersionUID = 1L;

 public EfemerideException(String mensaje) {
  super(mensaje);
 }
 
}

CLASE EFEMERIDES

public class Efemerides implements IEfemerides {

 @Override
 public void insertar(Efemeride efemeride) throws EfemerideException {
  try {
   Connection conexion = BaseDatos.getConnection();
   String sql = "insert into efemerides (texto, fecha) values (?, ?)";
   PreparedStatement insertar = conexion.prepareStatement(sql);

   insertar.setString(1, efemeride.getTexto());
   insertar.setDate(2, DateUtils.convertir(efemeride.getFecha()));

   insertar.executeUpdate();
   insertar.close();

  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se ha podido insertar la efeméride.");
  }
 }

 @Override
 public void eliminar(Integer id) throws EfemerideException {
  try {
   int eliminado;
   Connection conexion = BaseDatos.getConnection();
   String sql = "delete from efemerides where id=?";
   PreparedStatement eliminar = conexion.prepareStatement(sql);

   eliminar.setInt(1, id);

   eliminado = eliminar.executeUpdate();
   if (eliminado == 0) {
    throw new EfemerideException("La efeméride no existe.");
   }
   eliminar.close();

  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se ha podido eliminar la efeméride.");
  }
 }

 @Override
 public void actualizar(Efemeride efemeride) throws EfemerideException {
  try {
   int actualizado;
   Connection conexion = BaseDatos.getConnection();
   String sql = "update efemerides set texto=?, fecha=? where id=?";
   PreparedStatement actualizar = conexion.prepareStatement(sql);

   actualizar.setString(1, efemeride.getTexto());
   actualizar.setDate(2, DateUtils.convertir(efemeride.getFecha()));
   actualizar.setInt(3, efemeride.getId());

   actualizado=actualizar.executeUpdate();
   if (actualizado == 0) {
    throw new EfemerideException("La efeméride no existe, por lo que no se ha podido actualizar.");
   }
   actualizar.close();

  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se ha podido actualizar la efeméride.");
  }

 }

 @Override
 public Efemeride recuperar(Integer id) throws EfemerideException {
  Efemeride efemeride = new Efemeride();
  try {
   Connection conexion = BaseDatos.getConnection();
   String sql = "select * from efemerides where id=?";
   PreparedStatement recuperar = conexion.prepareStatement(sql);

   recuperar.setInt(1, id);

   ResultSet resultado = recuperar.executeQuery();
   if (!resultado.next()) {
    throw new EfemerideException("La efeméride no se ha recuperado porque no existe.");
   } else {
    efemeride.setId(id);
    efemeride.setTexto(resultado.getString("texto"));
    efemeride.setFecha(resultado.getDate("fecha"));
   }
  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se ha podido recuperar la efeméride.");
  }
  return efemeride;
 }

 @Override
 public List<Efemeride> hoy() throws EfemerideException {
  Date hoy = new Date();

  return recuperarPorFecha(hoy);
 }

 @Override
 public List<Efemeride> recuperarTodas() throws EfemerideException {
  List<Efemeride> listado = new ArrayList<Efemeride>();
  try {
   Connection conexion = BaseDatos.getConnection();
   Statement recuperar = conexion.createStatement();

   ResultSet resultado;
   resultado = recuperar.executeQuery("select * from efemerides");

   while (resultado.next()) {
    Efemeride efemeride = new Efemeride();
    efemeride.setId(resultado.getInt("id"));
    efemeride.setTexto(resultado.getString("texto"));
    efemeride.setFecha(resultado.getDate("fecha"));
    listado.add(efemeride);
   }
  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se han podido recuperar las efemérides.");
  }
  return listado;
 }

 @Override
 public List<Efemeride> recuperarPorFecha(Date fecha)
   throws EfemerideException {
  List<Efemeride> listado = new ArrayList<Efemeride>();
  try {
   Connection conexion = BaseDatos.getConnection();
   String sql = "select * from efemerides where day(fecha)=? and month(fecha)=?";
   PreparedStatement recuperar = conexion.prepareStatement(sql);

   recuperar.setInt(1, DateUtils.dia(fecha));
   recuperar.setInt(2, DateUtils.mes(fecha));

   ResultSet resultado = recuperar.executeQuery();
   while (resultado.next()) {
    Efemeride efemeride = new Efemeride();
    efemeride.setId(resultado.getInt("id"));
    efemeride.setTexto(resultado.getString("texto"));
    efemeride.setFecha(resultado.getDate("fecha"));
    listado.add(efemeride);
   }
  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se han podido recuperar las efemérides.");
  }
  return listado;
 }

}

Finalmente, la aplicación con la que interactuará el usuario se creó utilizando varias clases proporcionadas por el profesor, que permitían crear menús y recoger los datos introducidos por el usuario.

CLASE MENUEFEMERIFE

public class MenuEfemeride {

 private static Efemerides efemerides = new Efemerides();
 
 public static void main(String[] args) {

  Menu principal = new Menu("Menú principal. Efemérides");
  Menu consultar = new Menu("Consultar");
  
  Accion insertarEfemeride = new Accion("Insertar efeméride") {
   public void accion() { onInsertarEfemeride(); }
  };
  Accion eliminarEfemeride = new Accion("Eliminar efeméride") {
   public void accion() { onEliminarEfemeride(); }
  };
  Accion actualizarEfemeride = new Accion("Actualizar efeméride") {
   public void accion() { onActualizarEfemeride(); }
  };
  Accion buscarPorId = new Accion("Buscar efeméride por identificador") {
   public void accion() { onBuscarPorId(); }
  };
  Accion buscarPorFecha = new Accion("Buscar efeméride por fecha") {
   public void accion() { onBuscarPorFecha(); }
  };
  Accion efemeridesHoy = new Accion("Efemérides de hoy") {
   public void accion() { onEfemeridesHoy(); }
  };
  Accion todas = new Accion("Todas las efemérides") {
   public void accion() { onTodas(); }
  };
  
  consultar.agregar(buscarPorId);
  consultar.agregar(buscarPorFecha);
  consultar.agregar(efemeridesHoy);
  consultar.agregar(todas);
  consultar.agregar(new OpcionSalir("Volver"));
  
  principal.agregar(insertarEfemeride);
  principal.agregar(eliminarEfemeride);
  principal.agregar(actualizarEfemeride);
  principal.agregar(consultar);
  principal.agregar(new OpcionSalir("Salir"));
  
  principal.ejecutar();
  
  BaseDatos.desconectar();

 }

 protected static void onInsertarEfemeride() {

  Efemeride efemeride = new Efemeride();
  
  String texto = Entrada.leerCadena("Introduzca el texto de la efeméride");
  String fechaTexto = Entrada.leerCadena("Introduzca la fecha (dd/mm/aaaa)");
  String[] partes = fechaTexto.split("/");
  
  GregorianCalendar fecha = new GregorianCalendar(Integer.parseInt(partes[2]), (Integer.parseInt(partes[1])-1), Integer.parseInt(partes[0]));

  efemeride.setTexto(texto);
  efemeride.setFecha(fecha.getTime());
  
  try {
   efemerides.insertar(efemeride);
   System.out.println("**EFEMÉRIDE INSERTADA CON ÉXITO**");
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
  
 }
 
 protected static void onEliminarEfemeride() {

  Integer id = Entrada.leerEntero("Introduzca el identificador de la efeméride a eliminar");
  
  try {
   efemerides.eliminar(id);
   System.out.println("**EFEMÉRIDE ELIMINADA**");
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
  
 }

 protected static void onActualizarEfemeride() {

  Efemeride efemeride = new Efemeride();
  Integer id = Entrada.leerEntero("Introduzca el identificador de la efeméride a actualizar");
  try {
   Efemeride recuperada = efemerides.recuperar(id);
   System.out.println("Datos de la efeméride a actualizar:");
   System.out.println("Id: "+id+" - Texto: "+recuperada.getTexto()+" - Fecha: "+DateUtils.formatear(recuperada.getFecha()));
   
   String texto = Entrada.leerCadena("Introduzca el nuevo texto de la efeméride");
   String fechaTexto = Entrada.leerCadena("Introduzca la nueva fecha (dd/mm/aaaa)");
   
   String[] partes = fechaTexto.split("/");
   GregorianCalendar fecha = new GregorianCalendar(Integer.parseInt(partes[2]), (Integer.parseInt(partes[1])-1), Integer.parseInt(partes[0]));

   efemeride.setId(id);
   efemeride.setTexto(texto);
   efemeride.setFecha(fecha.getTime());
   
   efemerides.actualizar(efemeride);
   System.out.println("**EFEMÉRIDE ACTUALIZADA CON ÉXITO**");
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
 }
 
 protected static void onBuscarPorId() {

  Integer id = Entrada.leerEntero("Introduzca el identificador de la efeméride a buscar");
  try {
   Efemeride efemeride = efemerides.recuperar(id);
   System.out.println("DATOS DE LA EFEMÉRIDE:");
   System.out.println("Id: "+id+" - Texto: "+efemeride.getTexto()+" - Fecha: "+DateUtils.formatear(efemeride.getFecha()));
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
 }
 
 protected static void onBuscarPorFecha() {

  String fechaTexto = Entrada.leerCadena("Introduzca la fecha (dd/mm) de las efemérides a buscar");
  String[] partes = fechaTexto.split("/");
  
  GregorianCalendar fecha = new GregorianCalendar(1999, (Integer.parseInt(partes[1])-1), Integer.parseInt(partes[0]));
  
  try {
   List <Efemeride> listado = efemerides.recuperarPorFecha(fecha.getTime());
   if (listado.isEmpty()) {
    System.out.println("**NO HAY EFEMÉRIDES PARA EL DÍA ESPECIFICADO**");
   }
   else {
    System.out.println("LISTADO DE LAS EFEMÉRIDES:");
    for (Efemeride efemeride : listado) {
     System.out.println("Id: "+efemeride.getId()+" - Texto: "+efemeride.getTexto()+" - Fecha: "+DateUtils.formatear(efemeride.getFecha()));
    }
   }
   Entrada.pausa();
   
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
  
 }
 
 protected static void onEfemeridesHoy() {
  
  try {
   List <Efemeride> listado = efemerides.hoy();
   if (listado.isEmpty()) {
    System.out.println("**NO HAY EFEMÉRIDES PARA EL DÍA DE HOY**");
   }
   else {
    System.out.println("LISTADO DE LAS EFEMÉRIDES DE HOY:");
    for (Efemeride efemeride : listado) {
     System.out.println("Id: "+efemeride.getId()+" - Texto: "+DateUtils.formatear(efemeride.getFecha()));
    }
   }
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
 }
 
 protected static void onTodas() {
  try {
   List <Efemeride> listado = efemerides.recuperarTodas();
   if (listado.isEmpty()) {
    System.out.println("**NO HAY EFEMÉRIDES ALMACENADAS**");
   }
   else {
    System.out.println("LISTADO DE TODAS LAS EFEMÉRIDES:");
    for (Efemeride efemeride : listado) {
     System.out.println("Id: "+efemeride.getId()+" - Texto: "+efemeride.getTexto()+" - Fecha: "+DateUtils.formatear(efemeride.getFecha()));
    }
   }
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }  
 }

}

También se creó una clase con utilidades para trabajar con las fechas, debido a que nos veíamos en la obligación de utilizar por una parte la clase java.util.Date y por otra java.sql.Date. Esta clase, como la clase "BaseDatos", se puede reutilizar cada vez que tengamos que trabajar con fechas en el acceso a bases de datos.

CLASE DATEUTILS

public class DateUtils {
 
 public static java.util.Date crearFecha(int dia, int mes, int anyo) {
  GregorianCalendar calendario = new GregorianCalendar(anyo, mes-1, dia);
  return calendario.getTime();
 }
 
 public static java.sql.Date convertir(java.util.Date fecha) {
  return new java.sql.Date(fecha.getTime());
 }
 
 public static int dia(java.util.Date fecha) {
  GregorianCalendar calendario = new GregorianCalendar();
  calendario.setTime(fecha);
  
  return calendario.get(Calendar.DAY_OF_MONTH);
 }
 
 public static int mes(java.util.Date fecha) {
  GregorianCalendar calendario = new GregorianCalendar();
  calendario.setTime(fecha);
  
  return calendario.get(Calendar.MONTH)+1;
 }
 
 public static int anyo(java.util.Date fecha) {
  GregorianCalendar calendario = new GregorianCalendar();
  calendario.setTime(fecha);
  
  return calendario.get(Calendar.YEAR);
 }
 
 public static String formatear(java.util.Date fecha) {
  SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
  return formatter.format(fecha);
 }

}

lunes, 31 de octubre de 2011

Clase "BaseDatos" y fichero de configuración

Hace algunos días comencé con el acceso a bases de datos desde Java y expliqué, brevemente, los pasos a seguir para implementar el puente JDBC-ODBC. Siguiendo con el tema de bases de datos, os dejo en esta entrada la clase "BaseDatos" y el fichero de configuración para el acceso a las bases de datos.

Cada proyecto nuevo en el que queramos acceder a una base de datos debe llevar tanto esta clase, como su correspondiente fichero de configuración, con los datos correspondientes.

La clase "BaseDatos" nos permitirá realizar todas las gestiones necesarias para acceder a una base de datos:
  • Registrar el driver.
  • Conectar a la base de datos.
  • Cerrar la conexión con la base de datos.
Al implementar esta clase, haremos que sólo se cree una conexión, que se utilizará para todos los accesos que se realicen a la base de datos en cada conexión. De esta manera no se tendrá que abrir y cerrar la conexión cada vez que se quiera acceder a la base de datos. Para conseguirlo el constructor de la clase es privado (no se podrá instanciar) y la conexión propiamente dicha será un atributo estático.

CLASE "BASEDATOS"

public class BaseDatos {
 
 private static Connection conexion = null;
 // Para utilizar el fichero de propiedades:
 private static ResourceBundle bundle = ResourceBundle.getBundle("dir.efemerides.config");
 
 // De esta manera no podemos instanciar BaseDatos
 private BaseDatos() {
 }
 
 public static Connection getConnection() throws SQLException {
  if (conexion == null || conexion.isClosed()) {
   conexion = conectar();
  }
  return conexion;
 }

 private static Connection conectar() {
  registrarDriver();
  Connection conexion = null;
  try {
   String url = bundle.getString("db.url");
   String username = bundle.getString("db.username");
   String password = bundle.getString("db.password");
   conexion = DriverManager.getConnection(url, username, password);
  } catch (SQLException e) {
   System.err.println("No fue posible establecer la conexión.");
   e.printStackTrace();
  }
  
  return conexion;
 }
 
 public static void desconectar() {
  try {
   if (conexion != null && !conexion.isClosed()) {
    conexion.close();
    conexion = null;
   }
  } catch (SQLException e) {
   System.err.println("No fue posible cerrar la conexión.");
   e.printStackTrace();
  }
 }
 
 private static void registrarDriver() {
  try {
   Class.forName(bundle.getString("db.driver"));
  } catch (ClassNotFoundException e) {
   System.err.println("Error al cargar el driver JDBC");
   e.printStackTrace();
  }
 }
}

El fichero de configuración tendrá los datos necesarios para acceder a la base de datos. Estos datos serán los que hayamos especificado al implementar el puente JDBC-ODBC.

La URL de conexión corresponde al nombre que le hayamos dado al origen de datos.

FICHERO DE CONFIGURACIÓN

# Driver de la base de datos:
db.driver=sun.jdbc.odbc.JdbcOdbcDriver

# Url de conexión:
db.url=jdbc:odbc:Efemerides

# Usuario y contraseña:
db.username=admin
db.password=1234

miércoles, 19 de octubre de 2011

Acceso a bases de datos Access - Puente JDBC-ODBC

Este curso hemos seguido con Java. El primer tema que hemos estado trabajando es el acceso a bases de datos utilizando este lenguaje. Inicialmente trabajaremos con MS Access, por lo que tenemos que implementar el puente JDBC-ODBC antes de empezar a trabajar con Java.

A continuación explico brevemente los pasos a seguir:

**Una vez creada la base de datos en MS Access, vamos al Panel de control.

**Elegimos "Herramientas administrativas".


**Doble clic en "Orígenes de datos ODBC".


**El origen de datos lo podemos crear en las pestañas "DSN de usuario" o "DSN de sistema", si queremos que esté disponible sólo para nosotros o para cualquier usuario del equipo.
**Hacemos clic en "Agregar...".


**Elegimos el driver. En este caso el de Microsoft Access y hacemos clic en "Finalizar".


**Se abre un cuadro como el siguiente. Indicamos el nombre que queremos dar al origen de datos y, si queremos, una pequeña descripción.


**Hacemos clic en "Seleccionar", para elegir la base de datos.


**La seleccionamos y hacemos clic en "Aceptar".


**Hacemos clic en "Avanzadas...".


**Especificamos el nombre de inicio de sesión y la contraseña.


**En el panel "Opciones", elegimos "Driver" y le damos como valor el mismo que hemos puesto como nombre del origen de datos. Hacemos clic en "Aceptar".


**Ya hemos creado el origen de datos para la base de datos creada previamente. Lo comprobamos en el listado.


Hay que tener en cuenta que se debe crear un origen de datos por cada base de datos que creemos. Si movemos esta base de datos a otro ordenador, también debemos crear de nuevo el origen de datos en ese equipo.
Espero que se entienda y sea útil.

miércoles, 5 de octubre de 2011

Multiplicación de matrices con JavaScript

Pues el título lo dice todo. Consiste en realizar un programa en JavaScript que multiplique dos matrices introducidas por el usuario. Para ello, en primer lugar, se piden las dimensiones de dichas matrices, se comprueba que son correctas [(m x n) * (n x p)] y si es así, se crean estas matrices, para que el usuario las rellene y posteriormente calcular su producto, que será otra matriz de dimensiones (m x p).

CÓDIGO HTML: pide las dimensiones de las matrices y ejecuta el código JavaScript

<html>
	<head>
		<script src="js/multiplicar_matrices4.js" language="javascript" type="text/javascript">
		</script>
	</head>
	<body>
		<div id="main" style="width:100%; height:350px">
			<div id="dimens" align="center" style="width:100%; background-color:FFA500">
				<div id="A" align="center" style="float:left; width:50%">
					<div>Dimensiones matriz A</div>
					<form name="dimA">
						Filas
						<input type="text" size="4" id="text">
						Columnas
						<input type="text" size="4" id="text">
					</form>
				</div>
				<div id="B" align="center" style="float:right; width:50%">
					<div>Dimensiones matriz B</div>
					<form name="dimB">
						Filas
						<input type="text" size="4" id="text">
						Columnas
						<input type="text" size="4" id="text">
					</form>
				</div>
				<input type="button" value="CREAR MATRICES" onclick="Comprobar ()" name="crear">
			</div>
	</body>
</html>

CÓDIGO JAVASCRIPT

var matriz1;
var matriz2;
var matrizRes;
var filaA;
var colA;
var filaB;
var colB;
var contador = 0;
//contador cuenta las veces que se accede, para que si no es la primera, se borren las capas creadas previamente.

//FUNCIONCES QUE DEBEMOS DEFINIR PARA CREAR LAS MATRICES
function CreaMatriz(n, m) {
	//DEFINIMOS EL TAMAÑO DE LA MATRIZ
	this.length = n;
	for (var i=0; i<n; i++) {
		this[i] = new Array(m);
	}
	return this;
}

function Multiplicar () {
	Inicializar ()
	for (i=0; i < filaA; i++){
		for (j=0; j < colB; j++){
			for (k=0; k < colA; k++){
				matrizRes[i][j] = matrizRes[i][j] + (matriz1[i][k] * matriz2[k][j]);
			}
		}
	}
}

function Mostrar () {
	Cargar ()
	
	var q = 0;
	
	for (i=0; i < matrizRes.length; i++){
		for (j=0; j < matrizRes.length; j++){
			document.matrizR.elements[q].value = matrizRes[i][j];
			matrizRes[i][j] = 0;
			q++;
		}
	}
}

//Esta función recoge los datos del formulario y los guarda en las matrices
function Cargar () {
	var q = 0;

	for (i=0; i<filaA; i++) {
		for (j=0; j<colA; j++) {
			matriz1[i][j] = parseInt(document.matrizA.elements[q].value);
			q++;
		}
	}
	
	q=0;
	for (i=0; i<filaB; i++) {
		for (j=0; j<colB; j++) {
			matriz2[i][j] = parseInt(document.matrizB.elements[q].value);
			q++;
		}
	}
	
	Multiplicar ()
}

//Comprueba que las dimensiones de las matrices son correctas para poder multiplicarlas
function Comprobar () {
	filaA = parseInt(document.dimA.elements[0].value);
	colA = parseInt(document.dimA.elements[1].value);
	filaB = parseInt(document.dimB.elements[0].value);
	colB = parseInt(document.dimB.elements[1].value);
		
	if (isNaN(filaA) || isNaN(colA) || isNaN(filaB) || isNaN(colB)) {
		alert("Valores no v\u00e1lidos.");
	}
	else if (colA != filaB) {
		alert("Dimensiones de las matrices no v\u00e1lidas.\nEl n\u00famero de columnas de A debe ser\nigual al n\u00famero de filas de B.");
	}
	else {
		if (contador > 0) {
			Borrar ()
		}
		matriz1 = new CreaMatriz(filaA, colA);
		matriz2 = new CreaMatriz(filaB, colB);
		CrearFormularios (filaA, colA, filaB, colB)
		matrizRes = new CreaMatriz(filaA, colB);
		CrearFormRes (filaA, colB)
		contador++
	}
}

function CrearFormularios (filA, colA, filB, colB) {
	var d = document.createElement("DIV");
	var fA = document.createElement("FORM");
	var fB = document.createElement("FORM");
	var A = document.createTextNode("Matriz A");
	var B = document.createTextNode("Matriz B");
	d.setAttribute("id", "matrices");
	d.setAttribute("align", "center");
	d.setAttribute("style", "width: 50%; height: 100%; float: left; background-color: 66FF66");
	fA.setAttribute("name", "matrizA");
	fB.setAttribute("name", "matrizB");
	
	var boton = document.createElement("INPUT");
	boton.setAttribute("type", "button");
	boton.setAttribute("value", "CALCULAR");
	boton.setAttribute("name", "button");
	boton.onclick=function(){Mostrar();}
	
	for (i=0; i<filA; i++) {
		var salto = document.createElement("BR");
		for (j=0; j<colA; j++) {
			var casilla = document.createElement("INPUT");
			casilla.setAttribute("type","text");
			casilla.setAttribute("size","4");
			casilla.setAttribute("name","text");
			fA.appendChild(casilla);
		}
		fA.appendChild(salto);
	}
	for (i=0; i<filB; i++) {
		var salto = document.createElement("BR");
		for (j=0; j<colB; j++) {
			var casilla = document.createElement("INPUT");
			casilla.setAttribute("type","text");
			casilla.setAttribute("size","4");
			casilla.setAttribute("name","text");
			fB.appendChild(casilla);
		}
		fB.appendChild(salto);
	}
	var salto = document.createElement("BR");
	d.appendChild(salto);
	d.appendChild(A);
	d.appendChild(fA);
	d.appendChild(B);
	d.appendChild(fB);
	var salto = document.createElement("BR");
	d.appendChild(salto);
	d.appendChild(boton);
	
	var otro = document.getElementById("main");
	otro.appendChild(d);
}

function CrearFormRes (filaA, colB) {
	var capa = document.createElement("DIV");
	var fRes = document.createElement("FORM");
	var res = document.createTextNode("Matriz Resultante");
	capa.setAttribute("id", "resultado");
	capa.setAttribute("align", "center");
	capa.setAttribute("style", "width: 50%; height: 100%; float:right; background-color: 20B2AA");
	fRes.setAttribute("name", "matrizR");
	
	for (i=0; i<filaA; i++) {
		var salto = document.createElement("BR");
		for (j=0; j<colB; j++) {
			var casilla = document.createElement("INPUT");
			casilla.setAttribute("type","text");
			casilla.setAttribute("size","4");
			casilla.setAttribute("name","text");
			casilla.readOnly ="true";
			fRes.appendChild(casilla);
		}
		fRes.appendChild(salto);
	}
	
	var salto = document.createElement("BR");
	capa.appendChild(salto);
	capa.appendChild(res);
	capa.appendChild(fRes);
	
	var otro = document.getElementById("main");
	otro.appendChild(capa);
}

function Inicializar () {
	for (i=0; i < matrizRes.length; i++){
		for (j=0; j < matrizRes.length; j++){
			matrizRes[i][j] = 0;
		}
	}
}

function Borrar () {
	var capa1 = document.getElementById("matrices");
	var capa2 = document.getElementById("resultado");
	var padre1 = capa1.parentNode;
	var padre2 = capa2.parentNode;
	padre1.removeChild(capa1);
	padre2.removeChild(capa2);
}