Accès rapide :
La vidéo
Présentation du composant KLink
Testons notre composant graphique
Cette vidéo vous apprend à coder un composant graphique Swing se présentant comme un lien hypertexte.
Par défaut, Swing ne propose pas de composant graphique se présentant comme un lien hypertexte. Or ce type de composant s'est fortement imposé dans les différentes interfaces graphiques que nous utilisons au quotidien. Voici un exemple d'utilisation (le lien a pour texte « Ping database »
Je vous propose donc une classe Swing permettant d'avoir ce type de composant.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
package fr.koor.swing; import java.awt.AWTEvent; import java.awt.Color; import java.awt.Cursor; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.Vector; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.border.Border; public class KLink extends JLabel { private static final long serialVersionUID = 1601118803426800680L; private static final Color LINK_COLOR = new Color( 51, 123, 200 ); private Vector<ActionListener> actionListeners = new Vector<>(); public KLink( String text ) { super( "<html><u>" + text + "</u></html>" ); this.setForeground( LINK_COLOR ); this.setCursor( Cursor.getPredefinedCursor( Cursor.HAND_CURSOR ) ); this.setFocusable( true ); this.addMouseListener( new MouseAdapter() { @Override public void mouseClicked( MouseEvent event ) { requestFocus(); fireActionEvent( event ); } }); this.addKeyListener( new KeyAdapter() { @Override public void keyPressed( KeyEvent event ) { if ( event.getKeyChar() == ' ' ) fireActionEvent( event ); } }); this.addFocusListener( new FocusListener() { @Override public void focusLost(FocusEvent arg0) { setBorder( null ); } @Override public void focusGained(FocusEvent arg0) { Border border = BorderFactory.createLineBorder( LINK_COLOR ); setBorder( border ); } }); } public void addActionListener( ActionListener listener ) { this.actionListeners.add( listener ); } public void removeActionListener( ActionListener listener ) { this.actionListeners.remove( listener ); } private void fireActionEvent( AWTEvent event ) { ActionEvent actionEvent = new ActionEvent( this, event.getID(), null ); for( var listener : actionListeners ) { listener.actionPerformed( actionEvent ); } } } |
Quelques explications complémentaires :
Pour souligner le texte du lien, nous utilisons la capacité d'un composant Swing d'afficher du HTML. Pour rappel, en HTML, le tag
<u>
permet de mettre une section de texte en souligné (Underline).
Le composant est rendu « focusable » (appel à this.setFocusable( true );
) : en utilisant la touche TAB, ou la séquence
SHIFT + TAB, on peut mettre le focus sur le composant KLink. Cela est requis si l'on veut permettre l'activation du lien par le clavier.
Les événements de type java.awt.event.FocusListener
sont interceptés pour permettre de détourer le composant en cas de prise de focus.
On en profite aussi pour mettre un curseur spécifique sur le composant en cas de prise de focus (appel à setCursor
).
Nous rajoutons le support pour un événement de type java.awt.event.ActionListener
. L'objectif étant de proposer la possibilité de ne coder
qu'un unique gestionnaire d'événements pour l'activation du lien, que l'on clique dessus avec la souris ou qu'on utilise le clavier.
Les événements de type java.awt.event.MouseListener
et java.awt.event.KeyListener
sont interceptés pour permettre le
déclenchement de l'ActionListener
.
Vous un petit exemple de fenêtre graphique embarquant une instance de KLink
. Pensez à tester la prise de focus en utilisant les touches TAB
ou SHIFT+TAB pour sélectionner le composant. Appuyez sur ESPACE pour activer le lien à partir du clavier.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
import java.awt.Checkbox; import java.awt.FlowLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.plaf.nimbus.NimbusLookAndFeel; import fr.koor.swing.KLink; public class Test extends JFrame { private static final long serialVersionUID = 4443303248990993973L; public Test() { super( "KLink component test" ); this.setSize( 400, 300 ); this.setLocationRelativeTo( null ); this.setDefaultCloseOperation( DISPOSE_ON_CLOSE ); // --- On récupère le contentPane --- JPanel contentPane = (JPanel) getContentPane(); contentPane.setLayout( new FlowLayout() ); // --- On ajoute des composants graphiques --- contentPane.add( new JButton( "Push me!" ) ); contentPane.add( new Checkbox( "Check me!" ) ); KLink link = new KLink( "Activate me!" ); link.addActionListener( (e) -> JOptionPane.showMessageDialog( this, "Link activated" ) ); contentPane.add( link ); } // --- Point d'entrée du programme --- public static void main(String[] args) throws Exception { UIManager.setLookAndFeel( new NimbusLookAndFeel() ); Test frame = new Test(); frame.setVisible(true); } } |
Améliorations / Corrections
Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.
Emplacement :
Description des améliorations :