2013-07-15 21 views
5

voglio aggiungere un hovering-effetto alla mia Swing.JButton personalizzata simile all'icona sul mio browser Chrome:swing JButton: che mostra bordo e lo sfondo solo quando è librato

Prima hover >>

enter image description here

Dopo hover >>

enter image description here

sono in grado di impostare il pulsante nella "prima" stato quando è stato creato, ma non sono in grado di creare il "bordo + sfondo in rilievo" quando è al passaggio del mouse. Quando tento di aggiungere nuovamente il bordo al pulsante, ho ottenuto un effetto in movimento, poiché dopo aver ridipinto un nuovo bordo è stato inserito.

Questo è il mio codice corrente:

public class MyButton extends JButton implements MouseListener { 

public MyButton(String iconPath, String toolTip) { 
    super(new ImageIcon(TipButton.class.getResource(iconPath))); 
    addMouseListener(this); 
    setBorder(null); 
    setBorderPainted(false); 
    setFocusPainted(false); 
    setOpaque(false); 
    setContentAreaFilled(false); 
    setToolTipText(toolTip); 
} 

public MyButton(String iconPath, String name, String toolTip) { 
    this(observers, iconPath, toolTip); 
    setText(name); 
} 

@Override 
public void mouseClicked(MouseEvent e) {} 

@Override 
public void mousePressed(MouseEvent e) {} 

@Override 
public void mouseReleased(MouseEvent e) {} 

@Override 
public void mouseEntered(MouseEvent e) { 
    if (e.getSource() != this) return; 

    setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED)); 
} 

@Override 
public void mouseExited(MouseEvent e) { 
    if (e.getSource() != this) return; 

    setBorder(null); 
} 

} 

Suppongo che la logica principale dovrebbe essere nei metodi mouseEntered/mouseExited ma non so come ottenere l'effetto desiderato. Qualche idea?

risposta

4

Penso di aver trovato una soluzione. L'uso di EmptyBorder con le stesse dimensioni (margini) di un bordo rialzato fa il trucco. Codice:

public class SwingUtils { 

public static JButton createMyButton (String iconPath, String toolTip) { 
    final JButton b = new JButton (new ImageIcon(SwingUtils.class.getResource(iconPath))); 
    final Border raisedBevelBorder = BorderFactory.createRaisedBevelBorder(); 
    final Insets insets = raisedBevelBorder.getBorderInsets(b); 
    final EmptyBorder emptyBorder = new EmptyBorder(insets); 
    b.setBorder(emptyBorder); 
    b.setFocusPainted(false); 
    b.setOpaque(false); 
    b.setContentAreaFilled(false); 
    b.setToolTipText(toolTip); 
    b.getModel().addChangeListener(new ChangeListener() { 
     @Override 
     public void stateChanged(ChangeEvent e) { 
      ButtonModel model = (ButtonModel) e.getSource(); 
      if (model.isRollover()) { 
       b.setBorder(raisedBevelBorder); 
      } else { 
       b.setBorder(emptyBorder); 
      } 
     } 
    }); 
    return b; 
} 

} 

Nota: come dice mKorbel sarebbe utilizzando ChangeListener e il pulsante creato in un metodo fabbrica invece di sottoclasse JButton.

+1

Ma perché c'è la necessità di ereditare 'JButton', guardando il codice, mi sembra, che non ce n'è. L'intera operazione può essere eseguita anche su una semplice istanza di 'JButton', come già suggerito da' mKorbel' (ecco perché ha risposto a questa risposta). Spero che considererete la composizione sull'ereditarietà, nell'attuazione effettiva del codice. –

+1

Rimosso ereditarietà e sostituito MouseListener con ChangeListener – Randomize

2

Utilizzare immagini diverse per ogni stato. È possibile impostare un'icona diversa per selezionato, disabilitato selezionato, disabilitato, premuto, rollover, rolloverEnabled, rolloverSelected. Maggiori informazioni here.

+0

Per il momento sto cercando di evitare di fare un'immagine aggiuntiva per ogni pulsante e di provare a ottenere l'effetto a livello di codice. – Randomize

+1

+1, mi piace questa idea, (anche se il mio voto arriverà tra 10 ore), dal momento che il mio limite è raggiunto per oggi :(Ecco un esempio [esempio] (http://stackoverflow.com/a/7919280/ 1057230) –

+0

grazie per i vostri commenti, per favore guarda la mia risposta – Randomize

1

In java 7 c'è una classe BevelBorder che sembra essere quello che stai cercando. I 2 metodi si sarà probabilmente interessato a sono

paintRaisedBevel(Component c, Graphics g, int x, int y, int width, int height) 

e

paintLoweredBevel(Component c, Graphics g, int x, int y, int width, int height) 

Ecco la documentazione sulla classe: http://docs.oracle.com/javase/7/docs/api/javax/swing/border/BevelBorder.html

+0

Mi è piaciuto il tuo suggerimento, anche perché non semplicemente: button.setBorder (BorderFactory.createBevelBorder (BevelBorder.RAISED/LOWERED)), guarda [BorderFactory.createBevelBorder (int) ] (http://docs.oracle.com/javase/7/docs/api/javax/swing/BorderFactory.html#createBevelBorder (int)) –

+1

Sì, penso onestamente che createBevelBorder (int) sia un'idea più semplice che funziona altrettanto bene, ma secondo il codice di Randomize, ci ha provato e ha avuto problemi, quindi sto solo offrendo una soluzione alternativa che potrebbe avere più successo con. – Collin

+0

Ahha, mio ​​male, non l'ho capito prima :(, anche se sarà un compito difficile da realizzare t, sottoclasse BevelBorder dato che il metodo specificato da te sta avendo lo specificatore di accesso protetto, anche se +1, ma come detto prima, potrebbe volerci del tempo per convertirlo in virtuale :-) –

1
  • lì (forse) c'è motivo di creare extends JButton implements MouseListener { , non sono presenti nessuno dei metodi JButton s e utilizzare invece la composizione con resi,

  • migliore potrebbe essere quella di creare una variabile locale e di utilizzare metodi implementati in API

  • sconsigliati i MouseListener per Buttons Components, tutti questi eventi sono implementate in JButtons API e correttamente

  • use set(Xxx)Icon for JButton

  • il più semplice dei modi è utilizzare JButton.getModel da ChangeListener, for example

+0

grazie per i vostri commenti. Per favore guarda la mia risposta. – Randomize