Java keyListener multi touche [Résolu/Fermé]

Signaler
Messages postés
608
Date d'inscription
mardi 12 janvier 2010
Statut
Membre
Dernière intervention
25 octobre 2015
-
Messages postés
608
Date d'inscription
mardi 12 janvier 2010
Statut
Membre
Dernière intervention
25 octobre 2015
-
Bonjour,

je suis un débutant en Java, mais assez passionné pour ne pas avoir la paix sans trouver une solution.

le problème peut etre intutilé "gestion des multi-touches dans l'interface KeyListener". mon programme affiche tt simplement en console, la liste des touches enfoncées.

l'empilement se passe très bien (avec un maximum de 4 a 5 touches), cependant la dépilation dans un sens ne fonctionne pas.

voici mon code:
import java.awt.event.KeyEvent;  
import java.awt.event.KeyListener;  
import java.util.HashSet;  
import java.util.Iterator;  

import javax.swing.JFrame;  

public class Clavier extends JFrame implements KeyListener {  
 private HashSet<Character> touches = new HashSet<Character>();  
 public Clavier(){  
  this.setSize(120, 100);  
  this.addKeyListener(this);  
  this.setLocationRelativeTo(null);  
  this.setVisible(true);  
  this.setDefaultCloseOperation(EXIT_ON_CLOSE);  
 }  
 @Override  
 public void keyPressed(KeyEvent arg0) {  
  touches.add(arg0.getKeyChar());  
 }  
 @Override  
 public void keyReleased(KeyEvent arg0) {  
  touches.remove(arg0.getKeyChar());  
  if(touches.isEmpty())  
   System.out.println("Aucune touche n'est enfoncée");  
 }  
 @Override  
 public void keyTyped(KeyEvent arg0) {  
  String message= new String("Les touches enfoncées sont: ");  
  Iterator iter= touches.iterator();  
  while(iter.hasNext()){  
   //if(e.)  
   message+=", "+iter.next();  
  }  
  System.out.println(message);  
 }  
   
 public static void main(String[] args) {  
  Clavier clavier= new Clavier();  
 }  
}  


Comment puis je résoudre ce problème?

je vous remercie d'avance chers internautes.

Being normal is boring... being geek is interesting

1 réponse

Messages postés
16121
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
30 novembre 2020
2 740
Tu peux avoir des problèmes si tu appuies par exemple sur [Shift] puis [C], car car ton code va ajouter le caractère 'C' (en majuscule), mais si tu relèves la touche [Shift] en gardant la touche [C] enfoncée, tu vas ajouter 'c' (minuscule) et tu vas avoir donc 'c' et 'C' en même temps. Quand tu relèveras la touche [C] seul le 'c' va être enlevé, et le 'C' va rester même si aucune touche n'est plus appuyée...

Puisque ce sont les touches qui t'intéresse (et non les caractères qu'ils représentent), je te conseille de considérer les KeyCode ou ExtendedKeyCode plutôt que les getChar, tu n'auras donc plus de problème de ce genre...

PS. J'ai pas mal amélioré le code ;-)

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.TreeSet;

import javax.swing.JFrame;
import javax.swing.JLabel;

class MultipleListener implements KeyListener
{
    private TreeSet<Integer> set = new TreeSet<Integer>();
    private final JLabel label;
    private final String EMPTY = "Press Any Key";
    
    public MultipleListener()
    {
        System.out.println(set);
        label = new JLabel(EMPTY,JLabel.CENTER);
    }
    
    public JLabel getLabel()
    {
        return label;
    }
    
    @Override
    public void keyPressed(KeyEvent e) 
    {
        if (set.add(e.getExtendedKeyCode()))
        {
            System.out.println(set);
            label.setText(set.toString());
        }
    }
    
    @Override
    public void keyReleased(KeyEvent e)
    {
        if(set.remove(e.getExtendedKeyCode()))
        {
            System.out.println(set);
            if (set.isEmpty())
                label.setText(EMPTY);
            else
                label.setText(set.toString());
        }
    }
    
    @Override
    public void keyTyped(KeyEvent e)
    {
    }
}

public class Test
{    
    public static void main(String[] args)
    {
        JFrame frame = new JFrame();
        frame.setSize(200,100);
                        
        MultipleListener listener = new MultipleListener();
        frame.add(listener.getLabel());
        frame.addKeyListener(listener);
        
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}
1
Merci

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

CCM 76687 internautes nous ont dit merci ce mois-ci

Messages postés
114
Date d'inscription
lundi 12 novembre 2012
Statut
Membre
Dernière intervention
29 août 2018
9
Bonjour,

Alors là bravo !!
On à enfin là solution et sans Thread en plus, moi qui ne les aime pas.

Merci KX.
Messages postés
16121
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
30 novembre 2020
2 740 >
Messages postés
114
Date d'inscription
lundi 12 novembre 2012
Statut
Membre
Dernière intervention
29 août 2018

"et sans Thread en plus"
La gestion des Listener en Java c'est quand même bien des Thread... Certes ils sont cachés, mais ils sont bien là. Et puis les Threads : "C'est pas si terrible!" ^^
Messages postés
608
Date d'inscription
mardi 12 janvier 2010
Statut
Membre
Dernière intervention
25 octobre 2015
72
Bonsoir KX,

si c possible une derniere explication, car j'ai pu comparé ton code avec le mien, ils se ressemblent en terme d'empilement et d la dépilation (bien sur vous utilisez le ExtendedKeyCode pour tester la présence de telle touche et pour ne pas boucler l'affichage).

mais je n'arrive pas comme meme a comprendre prkoi la dépilation ne fonctionnait pas pr moi?
bien sur, je considere dans le cas general (caractère minuscules), l'équivalence du caractère avec son code. ou bien c'est cette équivalence qui me fait tromper?

et si tu connais une documentation qui explique plus ceci, n'hésiter pas de la citer.

merci encore pr tes remarques.
Messages postés
16121
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
30 novembre 2020
2 740 >
Messages postés
608
Date d'inscription
mardi 12 janvier 2010
Statut
Membre
Dernière intervention
25 octobre 2015

"j'ai pu comparé ton code avec le mien, ils se ressemblent"
Bien sûr, je suis parti du tien comme base. Après j'ai fait quelques améliorations (notamment pour l'affichage), mais la seule différence fondamentale c'est le problème des Char/KeyCode que j'ai expliqué en détail tout à l'heure.

Tu "empilais" un char qui est le résultat d'une combinaison de touches particulières au moment du keyPressed, mais tu "dépilais" au moment du KeyReleased le résultat d'une combinaison de touches qui était parfois différente, donc cela ne coïncidait pas.

C'est pour ça qu'il vaut mieux considérer les KeyCode, parce que les touches sont alors considérés indépendamment de leur ordre de pression, et donc du rôle qu'elles jouent dans la combinaison de caractères.

PS. Les termes empilés et dépilés sont réservés au vocabulaire des piles (et par extensions aux collections LIFO), alors qu'ici on est dans des ensembles ordonnés par la valeur, pas par le temps (remarque : j'ai pris un TreeSet parce que c'est plus performant qu'un HashSet quand on a peu de valeurs comme ici, mais ça ne change rien au résultat)
Messages postés
608
Date d'inscription
mardi 12 janvier 2010
Statut
Membre
Dernière intervention
25 octobre 2015
72
Bonsoir,

merci, c'est cette explication qui va me rendre la paix.
ça m'a énormément éclairé la notion des touches et des caractères.

Merci Beaucoup KX