JLabel editable

24 02 2010

Los JLabel son elementos no editables. Lo cual tiene sentido. Están pensadas para mostrar información, posiblemente, etiquetando otro elemento.

En la aplicación que estoy construyendo queremos que unos componentes personalizados sirvan para mostrar información pero a su vez permitan editarla y queremos diferenciar claramente si el componente está en modo edición o no. En definitiva queremos tener etiquetas que bajo según qué circunstancias se puedan editar. Puesto que el JLabel no nos brinda esta opción, hemos tenido que trabajar un poco más y crear un componente personalizado.

El truco consistente en tener un componente, por ejemplo un JPanel, con un layout del tipo CardLayout con dos ‘cartas’ una de las cuales muestra una JLabel de toda la vida y otra un JTextField. El componente aporta la lógica para cambiar la carta en respuesta a ciertas interacciones del usuario. Si mantenemos el contenido de los dos componentes de forma coherente, tenemos la ilusión que la etiqueta se convierte en un campo de texto cuando entramos en modo edición y al revés al salir de este modo.

El siguiente código muestra una versión incipiente (pero funcional) de este ‘etiqueta editable’. Para entrar en modo edición hacemos doble click en la etiqueta y para salir del estado de edición pulsamos RETURN para confirmar los cambios o ESCAPE para cancelarlos.

Tomadlo como una prueba de concepto (que es lo que es) y no como una clase terminada con calidad industrial.

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;
	}
}
Anuncios

Acciones

Information

One response

10 08 2010
MagMax

Hola.

Siempre depende de para qué necesitas exactamente el componente, pero creo que hay una solución mucho más sencilla, al menos para el 90% de los casos.

Consiste en usar jTextField y quitar los jLabel. Jugando con las propiedades “editable” y “border” se puede conseguir un “look and feel” como un jLabel.

Para completar el panel, puedes crearte una lista de jTextFields, y con dos simples bucles puedes hacer que todos los elementos tengan borde y sean editables o ninguna de éstas.

Si quieres que esté en negrita, también puedes hacerlo con la propiedad “Font”.

Tan solo se me ocurre que pueda ser interesante esta clase en dos casos: Que se necesite una propiedad que tienen los jLabel y no tienen los jTextField, o bien que tan solo sea un ejemplo de algo que se podría hacer con otro componente diferente, pero que se ha hecho con éstos por ser de los más sencillos.

La verdad es que me gustaría saber tu opinión de lo que propongo 😀

Muchas gracias!!

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s




A %d blogueros les gusta esto: