martes, agosto 29, 2006

Java: personalizando JFileChooser

Recientemente, programando en java, he necesitado modificar un JFileChooser para poder introducir un componente adicional en la misma línea de los botones de control (abrir y cancelar).

El JFileChooser es una clase un poco especial, ya que usa bastantes componentes nativas en el UI. Buscando por internet he encontrado algunas ideas que me han sido útiles, pero nada concreto que me resolviese el problema del todo.

Quería agregar un JCheckBox con una opción, para que el fichero abriese una sesión en la misma ventana de una aplicación o en una nueva, y pensé que el JFileChooser era un lugar apropiado para ofrecer la opción.

El truco está en sustituir la parte baja del panel con uno nuevo, que incluya dos botones que emulen a los anteriores, y que contenga además el resto de componentes que necesitemos. Otro truco está en hacer que con un PropertyListener se agregue el nuevo panel en el momento adecuado, ya que si no se hace así no funciona.

El resultado sería algo así:


Y el código fuente sería:

------------------------------------------------

import java.awt.BorderLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JPanel;

/**
* Ejemplo de personalización de JFileChooser
* @author airon
* Publicado en http://webpacifica.blogspot.com/
*/
public class CustomJFileChooser extends JFileChooser
{
public CustomJFileChooser (JComponent component)
{
super();
this.setControlButtonsAreShown(false);

JButton acceptB = new JButton("Open");
JButton cancelB = new JButton("Cancel");

final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel,BoxLayout.X_AXIS));
panel.add(component);
panel.add(Box.createHorizontalGlue());
panel.add(acceptB);
panel.add(Box.createHorizontalStrut(4));
panel.add(cancelB);

Insets insets = this.getInsets();

panel.setBorder(BorderFactory.createEmptyBorder(
insets.top,
((insets.left>=2)?insets.left-2:insets.left),
insets.bottom,insets.right));

acceptB.addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent arg0) {
approveSelection();
}

});

cancelB.addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent arg0) {
cancelSelection();
}

});

// Tricky way to add an extra component to the dialog
addPropertyChangeListener("ancestor",
new PropertyChangeListener(){
public void propertyChange(PropertyChangeEvent arg0)
{
getParent().add(panel,BorderLayout.SOUTH);
}
});
}


public static void main (String args[])
{
JCheckBox cb = new JCheckBox("Hello!",false);
JFileChooser jfc = new CustomJFileChooser(cb);
int returnVal = jfc.showOpenDialog(null);
System.out.println("Checkbox selected: "+cb.isSelected());

System.exit(0);
}
}

No hay comentarios: