2012-04-11 12 views

Antwort

7

Es gibt ein paar Optionen, und jeder von ihnen hat seine eigenen Vor- und Nachteile ...

  1. Erstellen eines benutzerdefinierten förmigen Fenster - mit diesem Ansatz einige Systeme zusätzliche Schatten hinter dem erstellen können geformtes Fenster, auch das funktioniert auf den meisten Systemen (sollte sogar auf Linux JDKs funktionieren). Das Schlechte an diesem Ansatz (der ihn tatsächlich unbrauchbar macht) ist die ungeprüfte Form-Grenzlinie - wenn Sie ein ellipsenförmiges Fenster erstellen, werden seine Seiten grob erscheinen.

  2. Erstellen Sie ein nicht-undurchsichtiges undekoriertes Fenster mit einer gezeichneten Form - dieser Ansatz löst das Hauptproblem des (1) Ansatzes. Sie können eine Alias-Form für das Zeichnen auf einem vollständig transparenten Fenster erstellen. Das Schlechte daran ist, dass es nur auf Win- und Mac-Systemen funktioniert. Auf (fast) jedem Linux-System erhalten Sie ein rechteckiges resultierendes Fenster und eine Unmenge an Fehlern bei nicht unterstützten Operationen.

  3. Erstellen Sie ein benutzerdefiniertes Popup im Java-Fenster und platzieren Sie es auf den Fensterlayer oder Glasscheiben. Auf diese Weise können Sie Kompatibilitätsprobleme vollständig vermeiden und die Vorteile des Ansatzes (2) nutzen. Es gibt jedoch eine schlechte Sache an diesem Ansatz - Sie können solche Popup nur in Fenster-Root-Bereich Grenzen anzeigen. Dies ist in den meisten Fällen immer noch viel besser als zwei andere, da es weniger Ressourcen verbraucht, keine zusätzlichen Fenster erstellt und Sie jeden Teil des Popups steuern können.

über den dritten Ansatz - Sie können ToolTipManager prüfen ich in meinem eigenen Projekt angelegt habe WebLookAndFeel - es nutzt Fensterglasscheibe mit einem Schatten-Effekt speziell geformten halbtransparenten Tooltips angezeigt werden soll. Ich werde auch bald genug Fenster PopupManager hinzufügen, das die schnelle Erstellung von "inneren" Fenster-Popups ermöglicht.

Hier sind einige Beispiele der Ansätze:

Ein bisschen Code,

in allen Beispielen verwendet voraus

Methode Form zu erstellen:

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

Maus-Adapter, erlaubt Verschieben des Fensters durch Ziehen der Komponente:

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

erster Ansatz Beispiel:

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

Wie Sie sehen können - Ecken der gerundeten Form sind ziemlich rau und nicht gut aussehende

2. Ansatz: Jetzt

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

es sollte perfekt aussehen - das einzige Problem, das nur unter Windows und Mac funktioniert (zumindest in 1.6.x JDK). Es war so ungefähr vor einem Monat, als ich es das letzte Mal auf verschiedenen Betriebssystemen überprüft habe.

3. Ansatz

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

Dies ist ein einfaches Beispiel für die Popup platziert auf Glasscheibe. Wie Sie sehen können, existiert es nur innerhalb des JFrames, hat aber die Alias-Seite und funktioniert auf jedem Betriebssystem korrekt.

+0

sehr gute Antwort +1 – mKorbel

+0

Ich habe die Code-Beispiele zu allen Ansätzen hinzugefügt –

+0

Ich bemerkte bereits das Problem und änderte den Text, aber danke für den Tipp :) –