2012-04-11 12 views

Respuesta

7

Hay algunas opciones y cada uno de ellos tiene sus propias ventajas y desventajas ...

  1. Crear una ventana en forma personalizada - con este enfoque algunos sistemas serán capaces de crear sombra adicional detrás de la en forma de ventana, también funciona en la mayoría de los sistemas (debería funcionar incluso en linux JDK). Lo malo de este enfoque (que en realidad lo hace inservible) es la línea de borde de forma sin relieve: si crea una ventana en forma de elipse, sus lados aparecerán ásperos.

  2. Crear una ventana no opaca no decorada con la forma dibujada: este enfoque solucionará el problema principal del enfoque (1). Puede alias forma está dibujando en una ventana totalmente transparente. Lo malo de esto es que solo funciona en sistemas Win y Mac. En (la mayoría de las veces) cualquier sistema de Linux obtendrá una ventana resultante de un rectángulo y toneladas de errores sobre operaciones no admitidas.

  3. Cree una ventana emergente con forma personalizada dentro de la ventana de java y colóquela en la ventana en capas o en paneles de vidrio. Esto le permitirá evitar por completo cualquier problema de compatibilidad y obtener los beneficios del enfoque (2). Sin embargo, hay algo malo sobre este enfoque: solo puede mostrar esa ventana emergente en los límites del panel de la ventana. Esto todavía es mucho mejor que otras dos formas en la mayoría de los casos, ya que utiliza menos recursos, no crea ventanas adicionales y puede controlar cada parte de la ventana emergente.

Sobre la tercera enfoque - puede comprobar TooltipManager he creado en mi propio proyecto WebLookAndFeel - Utiliza panel de cristal de la ventana para mostrar en forma personalizada sobre herramientas semi-transparente con una sombra-efecto. También muy pronto agregaré la ventana PopupManager que permitirá la creación rápida de ventanas emergentes "internas".

Éstos son algunos ejemplos de los enfoques:

Un pedazo de código que utiliza delante en todos los ejemplos

Método para crear la forma:

private static Area createShape() 
{ 
    Area shape = new Area (new RoundRectangle2D.Double (0, 20, 500, 200, 20, 20)); 

    GeneralPath gp = new GeneralPath (GeneralPath.WIND_EVEN_ODD); 
    gp.moveTo (230, 20); 
    gp.lineTo (250, 0); 
    gp.lineTo (270, 20); 
    gp.closePath(); 
    shape.add (new Area (gp)); 

    return shape; 
} 

adaptador de ratón que permite para mover la ventana arrastrando el componente:

public static class WindowMoveAdapter extends MouseAdapter 
{ 
    private boolean dragging = false; 
    private int prevX = -1; 
    private int prevY = -1; 

    public WindowMoveAdapter() 
    { 
     super(); 
    } 

    public void mousePressed (MouseEvent e) 
    { 
     if (SwingUtilities.isLeftMouseButton (e)) 
     { 
      dragging = true; 
     } 
     prevX = e.getXOnScreen(); 
     prevY = e.getYOnScreen(); 
    } 

    public void mouseDragged (MouseEvent e) 
    { 
     if (prevX != -1 && prevY != -1 && dragging) 
     { 
      Window w = SwingUtilities.getWindowAncestor (e.getComponent()); 
      if (w != null && w.isShowing()) 
      { 
       Rectangle rect = w.getBounds(); 
       w.setBounds (rect.x + (e.getXOnScreen() - prevX), 
         rect.y + (e.getYOnScreen() - prevY), rect.width, rect.height); 
      } 
     } 
     prevX = e.getXOnScreen(); 
     prevY = e.getYOnScreen(); 
    } 

    public void mouseReleased (MouseEvent e) 
    { 
     dragging = false; 
    } 
} 

primero ejemplo enfoque:

public static void main (String[] args) 
{ 
    JFrame frame = new JFrame(); 
    frame.setUndecorated (true); 

    JPanel panel = new JPanel(); 
    panel.setBackground (Color.BLACK); 
    WindowMoveAdapter wma = new WindowMoveAdapter(); 
    panel.addMouseListener (wma); 
    panel.addMouseMotionListener (wma); 
    frame.getContentPane().add (panel); 

    Area shape = createShape(); 
    AWTUtilities.setWindowShape (frame, shape); 
    frame.setSize (shape.getBounds().getSize()); 
    frame.setLocationRelativeTo (null); 

    frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); 
    frame.setVisible (true); 
} 

como se puede ver - esquinas de la forma redondeada son bastante duros y no de buen aspecto

segundo enfoque:

public static void main (String[] args) 
{ 
    JFrame frame = new JFrame(); 
    frame.setUndecorated (true); 

    final Area shape = createShape(); 
    JPanel panel = new JPanel() 
    { 
     protected void paintComponent (Graphics g) 
     { 
      super.paintComponent (g); 

      Graphics2D g2d = (Graphics2D) g; 
      g2d.setRenderingHint (RenderingHints.KEY_ANTIALIASING, 
        RenderingHints.VALUE_ANTIALIAS_ON); 

      g2d.setPaint (Color.BLACK); 
      g2d.fill (shape); 
     } 
    }; 
    panel.setOpaque (false); 
    WindowMoveAdapter wma = new WindowMoveAdapter(); 
    panel.addMouseListener (wma); 
    panel.addMouseMotionListener (wma); 
    frame.getContentPane().add (panel); 

    AWTUtilities.setWindowOpaque (frame, false); 
    frame.setSize (shape.getBounds().getSize()); 
    frame.setLocationRelativeTo (null); 

    frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); 
    frame.setVisible (true); 
} 

Ahora debería verse perfecto, el único problema es que esto funcionará solo en Windows y Mac (al menos en 1.6.x JDK). Al menos fue hace aproximadamente un mes cuando la última vez que lo revisé en varios sistemas operativos.

tercera enfoque

public static void main (String[] args) 
{ 
    JFrame frame = new JFrame(); 

    JPanel panel = new JPanel (new BorderLayout()); 
    panel.setOpaque (false); 
    WindowMoveAdapter wma = new WindowMoveAdapter(); 
    panel.addMouseListener (wma); 
    panel.addMouseMotionListener (wma); 
    frame.getContentPane().add (panel); 

    panel.add (new JButton ("Test")); 

    final Area shape = createShape(); 

    JPanel glassPane = new JPanel (null) 
    { 
     public boolean contains (int x, int y) 
     { 
      // This is to avoid cursor and mouse-events troubles 
      return shape.contains (x, y); 
     } 
    }; 
    glassPane.setOpaque (false); 
    frame.setGlassPane (glassPane); 
    glassPane.setVisible (true); 

    JComponent popup = new JComponent() 
    { 
     protected void paintComponent (Graphics g) 
     { 
      super.paintComponent (g); 

      Graphics2D g2d = (Graphics2D) g; 
      g2d.setRenderingHint (RenderingHints.KEY_ANTIALIASING, 
        RenderingHints.VALUE_ANTIALIAS_ON); 

      g2d.setPaint (Color.BLACK); 
      g2d.fill (shape); 
     } 
    }; 
    popup.addMouseListener (new MouseAdapter() 
    { 
     // To block events on the popup 
    }); 
    glassPane.add (popup); 
    popup.setBounds (shape.getBounds()); 
    popup.setVisible (true); 

    frame.setSize (800, 500); 
    frame.setLocationRelativeTo (null); 

    frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); 
    frame.setVisible (true); 
} 

Este es un ejemplo sencillo del emergente colocado en el cristal de una ventana. Como puede ver, existe solo dentro de JFrame, pero tiene el lado de alias y funciona correctamente en cualquier tipo de sistema operativo.

+0

muy buena respuesta +1 – mKorbel

+0

He añadido el código de muestras a todos los enfoques –

+0

Ya noté el problema y cambié el texto, pero gracias por el consejo :) –

Cuestiones relacionadas