2016-05-18 8 views
3

Ich versuche, eine JButton mit einer JLayer zu umhüllen, um einige Effekte/Funktionen hinzuzufügen. Wenn ich die Schaltfläche mit dem Wrapper in einer Symbolleiste auswähle, wird aus irgendeinem Grund eine Schaltfläche angezeigt. In der Symbolleiste wurde Rollover auf true festgelegt.Eine Rollover-Toolbar-Schaltfläche mit JLayer wird mit einem Rahmen versehen

enter image description here

Warum ist das passiert und wie kann ich das verhindern?

import java.awt.AWTEvent; 
import java.awt.BorderLayout; 
import java.awt.Graphics; 
import java.awt.event.MouseEvent; 
import javax.swing.JButton; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JLayer; 
import javax.swing.JToolBar; 
import javax.swing.SwingUtilities; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.plaf.LayerUI; 

public class JLayerButton extends JFrame { 

    private JToolBar toolbar; 
    private JButton button1; 
    private JButton button2; 
    private JButton button3; 

    public JLayerButton() { 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 
     setTitle("JLayer Button"); 
     setLayout(new BorderLayout()); 

     toolbar = new JToolBar(); 
     toolbar.setFloatable(false); 
     toolbar.setRollover(true); 
     getContentPane().add(toolbar, BorderLayout.NORTH); 

     button1 = new JButton("One"); 
     button1.setFocusable(false); 
     toolbar.add(button1); 
     button2 = new JButton("Two"); 
     button2.setFocusable(false); 
     toolbar.add(button2); 
     button3 = new JButton("Three"); 
     button3.setFocusable(false); 
     toolbar.add(button3); 

     // wrap button2 in JLayer 
     int componentIndex = toolbar.getComponentIndex(button2); 
     JButtonLayerUI layerUI = new JButtonLayerUI(); 
     JLayer<JButton> layer = new JLayer<JButton>(button2, layerUI); 
     layer.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK); 
     layer.setFocusable(false); 
     toolbar.add(layer, componentIndex); 

     setSize(300, 200); 
     setLocationRelativeTo(null); 
    } 

    public static void main(String[] args) 
      throws ClassNotFoundException, InstantiationException, 
      IllegalAccessException, UnsupportedLookAndFeelException { 
     UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 

     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new JLayerButton().setVisible(true); 
      } 
     }); 
    } 

    private static class JButtonLayerUI extends LayerUI<JButton> { 

     public JButtonLayerUI() { 
     } 

     @Override 
     public void paint(Graphics g, JComponent c) { 
      super.paint(g, c); 
     } 

     @Override 
     protected void processMouseEvent(MouseEvent e, JLayer<? extends JButton> l) { 
      onMouseEvent(l, e); 
     } 

     @Override 
     protected void processMouseMotionEvent(MouseEvent e, JLayer<? extends JButton> l) { 
      onMouseEvent(l, e); 
     } 

     private void onMouseEvent(JLayer<? extends JButton> l, MouseEvent e) { 
      System.out.println(e); 
     }   

    } 
} 

Antwort

4

Was möchten Sie scheinen möglich mit JLayer, da nicht zu erreichen:

aus dem Code of BasicToolBarUI, können wir diese Anrufe

installRolloverBorders heißt siehe installieren grenzt an die JToolBar :

public void setRolloverBorders(boolean rollover) { 
     rolloverBorders = rollover; 

     if (rolloverBorders) { 
      installRolloverBorders(toolBar); 
     } else { 
      installNonRolloverBorders(toolBar); 
     } 
    } 

installRolloverBorders Anrufe setBorderToRollover auf jedem der direktenJComponent Childs (nicht rekursiv) der Symbolleiste

protected void installRolloverBorders (JComponent c) { 
     // Put rollover borders on buttons 
     Component[] components = c.getComponents(); 

     for (Component component : components) { 
      if (component instanceof JComponent) { 
       ((JComponent) component).updateUI(); 
       setBorderToRollover(component); 
      } 
     } 
    } 

Schließlich wird setBorderToRollover nur auf Fälle von AbstractButton arbeiten, die Ihre JLayer nicht ist. Die ursprünglichen Ränder der Schaltflächen Ihres JLayers sind also nicht betroffen.

protected void setBorderToRollover(Component c) { 
     if (c instanceof AbstractButton) { 
      AbstractButton b = (AbstractButton)c; 

      Border border = borderTable.get(b); 
      if (border == null || border instanceof UIResource) { 
       borderTable.put(b, b.getBorder()); 
      } 

      // Only set the border if its the default border 
      if (b.getBorder() instanceof UIResource) { 
       b.setBorder(getRolloverBorder(b)); 
      } 

      rolloverTable.put(b, b.isRolloverEnabled()? 
           Boolean.TRUE: Boolean.FALSE); 
      b.setRolloverEnabled(true); 
     } 
    } 

Um es zusammenzufassen, die Roll Effekt nur auf Komponenten Treffen diese beiden Bedingungen arbeiten:

  1. Seien Sie ein direkt Kind der eine Instanz von JToolBar
  2. Be AbstractButton

Sie könnten wahrscheinlich r oll Ihre eigene Version von BasicToolBarUI und überschreiben Sie einige Methoden zum Hinzufügen von Rekursivität zum Beispiel, sehen Sie, ob es die Zeit wert ist.

+0

Ich sehe. Dies erklärt das Warum. Ich denke, ich muss nur mit dieser Grenze leben. Die Erweiterung 'BasicToolBarUI' wäre wahrscheinlich eine schlechte Idee. – predi

+0

Ja, es kann Nebenwirkungen auf andere Teile haben, Sie haben Recht. – Berger

Verwandte Themen