IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

AWT/Swing Java Discussion :

Association de touches spéciales


Sujet :

AWT/Swing Java

  1. #1
    Membre émérite
    Avatar de divxdede
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    525
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2004
    Messages : 525
    Par défaut Association de touches spéciales
    Bonjour,

    J'ai une application avec plusieurs JInternalFrame.
    Chacune des JInternalFrame doivent gérer raccourcis de touches que sont
    - PAGE UP
    - PAGE DOWN

    Ces deux touches auront un comportement métier.

    Naïvement je pensais m'en sortir avec un code du style:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Action    prevAction = ........;
    Action    nextAction = ........;
     
    InputMap  inputMap   = container.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
    ActionMap actionMap  = container.getActionMap();
     
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP , 0,"prev");
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN , 0,"suiv");
     
    actionMap.put("prev", prevAction );
    actionMap.put("suiv", nextAction );
    Sachant que "container" represente le "ContentPane" d'une JInternalFrame.

    Le problème:
    - Les JScrollPane attrapes avant moi l'evenement liés aux touches PAGE_UP / PAGE_DOWN pour gérer l'avancement des barres de défilements.

    Comment m'en sortir simplement sachant que je ne sais pas d'avance ce qui sera construit "graphiquement" a l'interieur de la JInternalFrame ?

  2. #2
    Membre éclairé
    Avatar de seiryujay
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    950
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 950
    Par défaut
    Voici un petit lien qui pourra t'être utile.
    Ca t'explique comment fonctionne tout ça, et notamment ce passage :
    If more than one binding exists for the key, only the first valid one found is used. Input maps are checked in this order:

    1) The focused component's WHEN_FOCUSED input map.
    2) The focused component's WHEN_ANCESTOR_OF_FOCUSED_COMPONENT input map.
    3) The WHEN_ANCESTOR_OF_FOCUSED_COMPONENT input maps of the focused component's parent, and then its parent's parent, and so on, continuing up the containment hierarchy. Note: Input maps for disabled components are skipped.
    4) The WHEN_IN_FOCUSED_WINDOW input maps of all the enabled components in the focused window are searched. Because the order of searching the components is unpredictable, avoid duplicate WHEN_IN_FOCUSED_WINDOW bindings!
    Dans ton cas, je pense que les WHEN_FOCUSED input map des scrollbars captent l'évènement avant tout le reste.

    Une solution qui pourrait marcher : désactiver les entrées "Pages prec." et "Page suiv." dans les input map de tes scrollpanes...
    Je m'étais créé cette méthode statique pour ajouter un KeyBinding à un composant quelconque :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    	/**
             * Méthode permettant d'ajouter un couple KeyStroke - Action au composant
             * passé en paramètre.
             * Utilisé pour faire du Key Binding.
             * cf http://java.sun.com/docs/books/tutorial/uiswing/misc/keybinding.html
             * 
             * @param KeyStroke ks : la combinaison de touches associée à l'action
             * @param AbstractAction action : l'action à exécuter lors de la combinaison de touches
             * @param inputMapType : le contexte dans lequel on doit exécuter l'action
             * lorsqu'on détecte la combinaison de touches.
             * 
             * Le paramètre inputMapType peut avoir les valeurs :
             *    - JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
             *    - JComponent.WHEN_IN_FOCUSED_WINDOW
             *    - JComponent.WHEN_FOCUSED
             */
    	public static void setKeyStrokeAction(JComponent component, KeyStroke ks, AbstractAction action, int inputMapType) {
    		/** Récupération de l'InputMap correspondant au type passé en paramètre*/
    		InputMap im = component.getInputMap(inputMapType);
     
    		/** Récupération de l'ActionMap de la dialog */
    		ActionMap am = component.getActionMap();
    		if (am == null)
    			am = new ActionMap();
     
    		/** Récupération des Command associées aux KeyStroke qui nous intéressent */
    		Object command = im.get(ks);
    		if (command == null) {
    			command = new Object();
    			im.put(ks, command);
    		}
     
    		/** Ajout du couple KeyStroke - Action */
    		am.put(command, action);
    	}
    Je dirai qu'on peut l'adapter pour enlever un KeyBinding, en faisant quelque chose comme ceci (non-testé...) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    	public static void removeKeyStrokeEntry(JComponent component, KeyStroke ks, int inputMapType) {
    		/** Récupération de l'InputMap correspondant au type passé en paramètre*/
    		InputMap im = component.getInputMap(inputMapType);
     
    		/** Suppression de l'entrée ks */
    		im.remove(ks);
    	}
    En espérant que ça fonctionne...

  3. #3
    Membre émérite
    Avatar de divxdede
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    525
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2004
    Messages : 525
    Par défaut
    Merci beaucoup.
    Cela m'a permis de bien éclaircir le mécanisme général de "key bindings" en swing.

    Cependant j'ai de ce fait essayé ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    Action    prevAction = ........;
    Action    nextAction = ........;
     
    removePageUpAndPageDownKeyBindings( container );
     
    InputMap  inputMap   = container.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
    ActionMap actionMap  = container.getActionMap();
     
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP , 0,"prev");
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN , 0,"suiv");
     
    actionMap.put("prev", prevAction );
    actionMap.put("suiv", nextAction );


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    private static void removePageUpAndPageDownKeyBindings(Container container)
    {
        if( container instanceof JInternalFrame )
        {
            removePageUpAndPageDownKeyBindings( ((JInternalFrame)container).getContentPane() );
            return;
        }
     
        if( container instanceof JComponent )
        {
            System.out.println("Removing PAGE_UP / PAGE_DOWN key bindings on " + container.getClass() + " instance");
     
            JComponent c = (JComponent)container;
            c.getInputMap( JComponent.WHEN_FOCUSED ).remove( KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP , 0 ) );
            c.getInputMap( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ).remove( KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP , 0 ) );
            c.getInputMap( JComponent.WHEN_IN_FOCUSED_WINDOW ).remove( KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP , 0 ) );
     
            c.getInputMap( JComponent.WHEN_FOCUSED ).remove( KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN , 0 ) );
            c.getInputMap( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ).remove( KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN , 0 ) );
            c.getInputMap( JComponent.WHEN_IN_FOCUSED_WINDOW ).remove( KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN , 0 ) );
        }
     
        /** Remove key bindings on all childs
         */
        for(int i = 0 ; i < container.getComponentCount() ; i++ )
        {
            /** JComponent extends Container
             */
            if( container.getComponent(i) instanceof Container )
                removePageUpAndPageDownKeyBindings( (Container)container.getComponent(i) );
        }
    }
    Ce test est un échec.
    Afin de verifier ma séquence faisant la liaison, j'ai essayé de faire l'association sur PAGE_UP + SHIFT et cela fonctionne correctement.

    Ce qui veut dire que ma tentative de removePageUpAndPageDownKeyBindings ne nettoie pas tout ce qu'il faut...

  4. #4
    Membre éclairé
    Avatar de seiryujay
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    950
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 950
    Par défaut
    As-tu essayé de rajouter tes 2 KeyStroke dans les autres InputMap de ton container ?

  5. #5
    Membre émérite
    Avatar de divxdede
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    525
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2004
    Messages : 525
    Par défaut
    Citation Envoyé par seiryujay
    As-tu essayé de rajouter tes 2 KeyStroke dans les autres InputMap de ton container ?
    Je viens de faire le test, cela ne fonctionne pas même dans les 3 inputMap.
    Mais si je change le KeyStroke (exemple PAGE_UP + SHIFT) alors ca fonctionne en l'etat (avec le code donné)

  6. #6
    Membre éclairé
    Avatar de seiryujay
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    950
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 950
    Par défaut
    Si ton container est une JFrame, essaie avec ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    	/**
             * Méthode permettant d'ajouter un couple KeyStroke - Action à la Dialog.
             * Utilisé pour faire du Key Binding.
             * cf http://java.sun.com/docs/books/tutorial/uiswing/misc/keybinding.html
             * 
             * @param KeyStroke ks : la combinaison de touches associée à l'action
             * @param AbstractAction action : l'action à exécuter lors de la combinaison de touches
             * @param inputMapType : le contexte dans lequel on doit exécuter l'action
             * lorsqu'on détecte la combinaison de touches.
             * 
             * Le paramètre inputMapType peut avoir les valeurs :
             *    - JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
             *    - JComponent.WHEN_IN_FOCUSED_WINDOW
             *    - JComponent.WHEN_FOCUSED
             */
    	public void setKeyStrokeAction(KeyStroke ks, AbstractAction action, int inputMapType) {
    		/** Récupération de l'InputMap correspondant au type passé en paramètre*/
    		InputMap im = getRootPane().getInputMap(inputMapType);
     
    		/** Récupération de l'ActionMap de la dialog */
    		ActionMap am = getRootPane().getActionMap();
    		if (am == null)
    			am = new ActionMap();
     
    		/** Ajout du couple KeyStroke - Action */
    		Object command = new Object();
    		im.put(ks, command);
    		am.put(command, action);
    	}
    C'est le code que j'applique pour les JFrame : il faut récupérer l'ActionMap du rootPane...

  7. #7
    Membre émérite
    Avatar de divxdede
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    525
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2004
    Messages : 525
    Par défaut
    Ce sont des JInternalFrame mais elles possédent la méthode getRootPane()

    Le résultat est identique.
    - en PAGE_UP cela ne fonctionne pas
    - en PAGE_UP + SHIFT cela fonctionne

  8. #8
    Membre émérite
    Avatar de divxdede
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    525
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2004
    Messages : 525
    Par défaut
    Finalement, le problème venait bien de la méthode removePageUpAndPageDownKeyBindings qui supprimait mal les actions.

    D'aprés le guide que tu as donné en lien il faut plutôt procéder comme suit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    c.getInputMap( JComponent.WHEN_FOCUSED ).put( KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP , 0 ) , "none" );
    En ajoutant le KeyStroke a l'id "none" alors tout fonctionne correctement.

  9. #9
    Membre éclairé
    Avatar de seiryujay
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    950
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 950
    Par défaut
    Citation Envoyé par divxdede
    Finalement, le problème venait bien de la méthode removePageUpAndPageDownKeyBindings qui supprimait mal les actions.
    J'avais prévenu que je n'avais pas testé

  10. #10
    Membre émérite
    Avatar de divxdede
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    525
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2004
    Messages : 525
    Par défaut
    Citation Envoyé par seiryujay
    J'avais prévenu que je n'avais pas testé
    Mais merci beaucoup du coup de pouce

  11. #11
    Membre éclairé
    Avatar de seiryujay
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    950
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 950
    Par défaut
    Avec plaisir !

  12. #12
    Membre averti
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    19
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 19
    Par défaut
    merci divxdede pour cette petite procedure très sympathique et pour la solution à un pb sur lequel je m'arrache les cheveux depuis deux jour.
    NB : pour ceux à qui ca pourrait servir, même apres le "nettoyage" des key binding il est necessaire de passer par les inputmap; KeyListener ne donne rien

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 07/11/2007, 11h06
  2. Réponses: 9
    Dernier message: 28/09/2007, 09h54
  3. comment associer la touche Enter à un bouton
    Par cerco1 dans le forum AWT/Swing
    Réponses: 18
    Dernier message: 15/08/2007, 13h44
  4. Intercepter l'appui sur les touches spéciales
    Par Mayhem dans le forum Windows
    Réponses: 1
    Dernier message: 05/01/2006, 21h31

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo