martes, 22 de noviembre de 2011

Diálogos personalizados, bordes redondeados, quitar botones de los diálogos.

Hola a todos.

Hace un tiempo tuve que pelearme mucho para encontrar la solución a 2 problemas bastante comunes. Los diseñadores que se encargan de la interfaz gráfica de la aplicación que estábamos desarrollando insistían en eliminar los botones clásicos que aparecen en el marco de los diálogos, si, si, los de minimizar, maximizar y cerrar, y querían utilizar unos personalizados.
Por si esto fuera poco, además pedían que los diálogos no tuviesen la forma cuadrada normal, si no que tuviesen bordes redondeados o formas específicas.

Pues bien, después de mucho indagar dí con la solución a ambos problemas de un plumazo. Paso a detallaros como hacerlo.

Un JDialog no es más que un Frame más de nuestra aplicación, como tal tiene los botones mencionados anteriormente, se le puede añadir un JMenu y demás parafernalia que muchas veces nos sobra en nuestros diseños.
Para conseguir quitar el marco exterior de los diálogos y mostrar solo el contenido, es decir, quitarle la decoración, la única manera de conseguirlo es llamar al método setUndecorated(true). Esto elimina estos botones y nos deja solo el contenido a la vista.

Esta condición anterior es necesaria para conseguir nuestro segundo objetivo, darles una forma personalizada a nuestras ventanas. Para ello nos valdremos de la clase de utilidades AWTUtilities, esta clase además de permitir cambiar la forma de las ventanas permite aplicar ciertas clases de transparencia a las mismas aunque los resultados no son siempre los esperados dependiendo de la plataforma de desarrollo (aunque esto es un tema que no vamos a tratar de momento). Esta clase se distribuye a partir de la JRE|JDK 6u10, por lo que los usuarios de versiones anteriores no podréis hacer uso de ella :(

Este sería el resultado que podríamos obtener haciendo uso de lo que os he comentado:


Bien, así pues aquí os dejo el código para conseguir estos resultados.

Primero la clase de nuestro diálogo personalizado, aquí simplemente heredamos de un JDialog, le quitaremos el marco y la botonera y en su método paint(Graphics g) haremos que se dibuje con la forma deseada.
package dialogos;

import java.awt.Graphics;
import java.awt.Shape;

import javax.swing.JDialog;

import com.sun.awt.AWTUtilities;

public class ShapedDialog extends JDialog {

 // La forma de nuestro dialogo
 Shape dialogShape;

 public ShapedDialog() {
  super();
  /* Con esta instruccion eliminamos la barra superior y los botones de
   * minimizar, maximizar y cerrar.
   */
  this.setUndecorated(true);
  // Esta orden centra el dialogo en la pantalla
  this.setLocationRelativeTo(null);
 }

 /**
  * Establece la forma de la ventana.
  * @param shape
  */
 public void setShape(Shape shape) {
  this.dialogShape = shape;
                /* Imprescindible para mostrar el diálogo, hasta que no hagamos esto,
   * la ventana permanece invisible
   */
  this.setVisible(true);
 }

 @Override
 public void paint(Graphics g) {

  // Pintamos todo el contenido
  super.paint(g);

  // Establecemos la forma de la ventana
  AWTUtilities.setWindowShape(this, dialogShape);

 }

}


Como veis ha sido bastante simple, a pesar de ello, a más de uno os habrá dolido la cabeza antes de llegar a este post, jeje.

Y ahora la clase desde donde lanzaremos nuestra aplicación y crearemos los diálogos.

package dialogos;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.RoundRectangle2D;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class Main {

 private static void createAndShowGUI() {
  JFrame frame = new JFrame("Ejemplos de dialogos");

  final ShapedDialog dialog = new ShapedDialog();
  // Este sera el contenido de nuestro dialogo
  JPanel dialogContent = new JPanel(new BorderLayout());
  dialogContent.add(new JLabel("Interior del dialogo", JLabel.CENTER), BorderLayout.CENTER);

  // Dado que eliminamos el boton de cerrar el dialogo, tendremos que añadirle un boton para ello
  JButton close = new JButton(new AbstractAction("Cerrar") {

   @Override
   public void actionPerformed(ActionEvent e) {
    dialog.dispose();
   }
  });
  dialogContent.add(close, BorderLayout.SOUTH);


  dialog.setContentPane(dialogContent);
  dialog.setSize(400, 200);

  JButton openDialog = new JButton();
  openDialog.setAction(new AbstractAction("Dialogo redondo") {

   @Override
   public void actionPerformed(ActionEvent e) {
    Shape oval = new Ellipse2D.Float(0, 0, 400, 200);
    dialog.setShape(oval);
   }
  });
  JButton openDialog2 = new JButton();
  openDialog2.setAction(new AbstractAction("Dialogo bordes redondeado") {

   @Override
   public void actionPerformed(ActionEvent e) {
    Shape roundRectangle = new RoundRectangle2D.Float(0, 0, 400, 200, 20, 20);
    dialog.setShape(roundRectangle);
   }
  });

  frame.getContentPane().setLayout(new FlowLayout());
     frame.getContentPane().add(openDialog);
     frame.getContentPane().add(openDialog2);
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     frame.setSize(200, 150);
     frame.setVisible(true);
 }

 public static void main(String[] args) {

  javax.swing.SwingUtilities.invokeLater(new Runnable() {
   public void run() {
    createAndShowGUI();
   }
  });
 }
}

Bien, pues esto es todo por hoy, espero que os estén siendo de ayuda estos mini-tutoriales.

Un saludo.

PD: ahora también podéis seguirme en Facebook y hacerme saber si os gusta lo que hago.

2 comentarios:

Anónimo dijo...

ñlnjkb j

Anónimo dijo...

Muy buen post! Saludos

Publicar un comentario