viernes, 14 de octubre de 2011

JLabel Editable en Java

En uno de mis proyectos de la universidad, me vi en la necesidad de utilizar una especie de JLabel pero que se pueda editar en tiempo de ejecución. La idea era que el usuario pueda utilizar un componente para etiquetar con una breve descripción a otros componentes gráficos de mi aplicación. Un JLabel como tal no se puede editar, un JTextField no me servía porque "jugar" con sus propiedades para que se parezca a un JLabel me pareció más complicado porque habría que conocer exactamente qué propiedades modificar y qué parámetros pasarle.

Por lo que buscando en la Red me encontré un código en el blog Bits y Bytes que permite construir un componente que "simula" un JLabel editable. El componente en cuestión sirve para mostrar información textual y a su vez permite editarla, y además permite diferenciar claramente si el componente está en modo de edición o no.

El uso del componente desde el punto de vista del usuario es sencillo: para entrar en modo de edición hacemos doble click sobre la etiqueta y para salir del modo de edición se presiona ENTER para confirmar los cambios, o ESCAPE para cancelarlos. El código para esta etiqueta editable, es el siguiente:
public class EditableLabel extends JPanel {
 /** The user is editing the component (JTextField is shown at the moment) */
 private boolean editing;

 /** The confirm edition key is Return */
 private static final int confirmKeyCode = KeyEvent.VK_ENTER;

 /** The cancel edition key is Return */
 private static final int cancelKeyCode = KeyEvent.VK_ESCAPE;

 /** The value which holds this component */
 private String value;

 // graphical components

 private CardLayout cl;
 private JPanel pnlCards;
 private static final String TEXT_FIELD = "text field";
 private JTextField textField;
 private static final String LABEL = "label";
 private JLabel label;

 public EditableLabel(String initialText) {
  this.value = initialText;

  cl = new CardLayout();
  pnlCards = new JPanel(cl);
  textField = new JTextField();
  label = new JLabel(initialText);
  pnlCards.add(textField, TEXT_FIELD);
  pnlCards.add(label, LABEL);
  cl.show(pnlCards, LABEL);
  add(pnlCards);

  // register the listeners
  label.addMouseListener(new MouseAdapter() {
   @Override
   public void mouseClicked(MouseEvent e) {
    // if double click, set edition mode
    if (e.getClickCount() == 2) {
     startEdition();
    }
   }
  });

  textField.addKeyListener(new KeyAdapter() {
   @Override
   public void keyReleased(KeyEvent e) {
    if (e.getKeyCode() == confirmKeyCode) {
     /* confirmation key pressed, so changing to non-edition
      * and confirm changes */
     confirmEdition();
    } else if (e.getKeyCode() == cancelKeyCode) {
     /* cancel key pressed, so changing to non edition and
      * cancel the changes */
     cancelEdition();
    }
   }
  });
 }

 private void startEdition() {
  cl.show(pnlCards, TEXT_FIELD);
  textField.setText(value);
  textField.requestFocus();
  textField.selectAll();
 }

 private void cancelEdition() {
  textField.setText(value);
  cl.show(pnlCards, LABEL);
 }

 private void confirmEdition() {
  value = textField.getText();
  label.setText(value);
  cl.show(pnlCards, LABEL);
 }

 /**
  * @return the value
  */
 public String getValue() {
  return value;
 }

 /**
  * @param value the value to set
  */
 public void setValue(String value) {
  this.value = value;
 }

 /**
  * @return returns true if the component is currently showing the text
  *  field or false otherwise.
  */
 public boolean isEditing() {
  return editing;
 }
}

Por comodidad para mi aplicación, yo le añadí un pequeño detalle a la aplicación: que además del ENTER para confirmar los cambios cuando nos encontramos en modo edición, también se lo pueda hacer con un click en cualquier parte del formulario.

Códifo Fuente: download/descargar

1 comentario :

Encuesta: ¿Quién es el mejor catedrático de la carrera de Ing. Informática de la UAGRM?