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 :

écouter un keyEvent sur une fenêtre


Sujet :

AWT/Swing Java

  1. #1
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2016
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2016
    Messages : 25
    Points : 23
    Points
    23
    Par défaut écouter un keyEvent sur une fenêtre
    Bonjour j'essais de réaliser un petit jeu.
    J'ai besoin que ma fenêtre puisse réagir à des appuis sur des touches du clavier.
    J'arrive à écouter un keyEvent à partir d'un JtextField mais le problème c'est que j'aimerais ne pas avoir à demander à l'utilisateur de cliquer sur un textfield pour pouvoir jouer.
    Comment puis je faire pour ne pas avoir à passer par le textfield?

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    Le plus simple est d'intervenir en dehors du système de focus.

    Exemple :
    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
    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
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
     
    public class DemoFrame extends JFrame {
     
    	private static final long serialVersionUID = 1L;
    	private MyPanel panel;
     
    	public DemoFrame() { 
    		super("Démo");
    		KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this::dispatchKeyEvent);
    		panel = new MyPanel();
    		panel.setBackground(Color.WHITE);
    		panel.setForeground(Color.BLUE);
    		add(panel);
    	}
     
    	private boolean dispatchKeyEvent(KeyEvent event) {
    		switch(event.getID()) {
    		case KeyEvent.KEY_PRESSED:
    			return dispatchKeyPressed(event);
    		case KeyEvent.KEY_TYPED:
    			return dispatchKeyTyped(event);
    		case KeyEvent.KEY_RELEASED:
    			return dispatchReleased(event);
    		default:
    			System.out.println(event);
    			return false;
    		}
    	}
     
    	private boolean dispatchReleased(KeyEvent event) {
    		System.out.println("Key Released : " + event);
    		return false;
    	}
     
    	private boolean dispatchKeyTyped(KeyEvent event) {
    		System.out.println("Key typed: " + event);
    		return false;
    	}
     
    	private boolean dispatchKeyPressed(KeyEvent event) {
    		switch(event.getKeyCode()) {
    		case KeyEvent.VK_UP:
    			System.out.println("UP");
    			panel.up();
    			return true; // on retourne true quand on veut que l'évenement ne soit plus traité par d'autre composant
    		case KeyEvent.VK_LEFT:
    			System.out.println("LEFT");
    			panel.left();
    			return true; // on retourne true quand on veut que l'évenement ne soit plus traité par d'autre composant
    		case KeyEvent.VK_RIGHT:
    			System.out.println("RIGHT");
    			panel.right();
    			return true; // on retourne true quand on veut que l'évenement ne soit plus traité par d'autre composant
    		case KeyEvent.VK_DOWN:
    			System.out.println("DOWN");
    			panel.down();
    			return true; // on retourne true quand on veut que l'évenement ne soit plus traité par d'autre composant
    		default:
    		}
    		return false;
    	}
     
    	private static class MyPanel extends JPanel {
     
    		private static final int SIZE=10;
     
    		private int x=0;
    		private int y=0;
    		private int dx=0;
    		private int dy=0;
     
    		private Timer animation;
     
    		public MyPanel() {
    			animation = new Timer(33, e->moveMobile());
    			addComponentListener(new ComponentAdapter() {
    				@Override
    				public void componentResized(ComponentEvent arg0) {
    					final int ox=x;
    					final int oy=y;
    					final int odx=dx;
    					final int ody=dy;
    					if ( x>getWidth()-SIZE ) {
    						x=getWidth()-SIZE;
    						dx=0;
    					}
    					if ( y>getHeight()-SIZE ) {
    						y=getHeight()-SIZE;
    						dy=0;
    					}
    					if ( odx!=dx || ody!=dy ) {
    						animate();
    					}
    					if ( ox!=x || oy!=y ) {
    						repaint();
    					}
    				}
    			});
    		}
     
    		private void moveMobile() {
    			final int ox=x;
    			final int oy=y;
    			final int odx=dx;
    			final int ody=dy;
    			if ( dx<0 ) {
    				x+=dx;
    				if ( x<0 ) {
    					x=0;
    					dx=0;
    				}
    			}
    			else if (dx>0 ) {
    				x+=dx;
    				if ( x>getWidth()-SIZE ) {
    					x=getWidth()-SIZE;
    					dx=0;
    				}
    			}
    			if ( dy<0 ) {
    				y+=dy;
    				if ( y<0 ) {
    					y=0;
    					dy=0;
    				}
    			}
    			else if (dy>0 ) {
    				y+=dy;
    				if ( y>getHeight()-SIZE ) {
    					y=getHeight()-SIZE;
    					dy=0;
    				}
    			}
    			if ( odx!=dx || ody!=dy ) {
    				animate();
    			}
    			if ( ox!=x || oy!=y ) {
    				repaint();
    			}
    		}
     
    		@Override
    		public void paint(Graphics g) {
    			super.paint(g);
    			((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    			g.setColor(getForeground());
    			g.fillOval(x, y, SIZE, SIZE);
    		}
     
    		public void left() {
    			dx--;
    			animate();
    		}
     
    		public void right() {
    			dx++;
    			animate();
    		}
     
    		public void up() {
    			dy--;
    			animate();
    		}
     
    		public void down() {
    			dy++;
    			animate();
    	}
     
    		private void animate() {
    			if ( dx!=0 || dy!=0 ) {
    				animation.start();
    			}
    			else {
    				animation.stop();
    			}
    		}
     
    	}
     
    	public static void main(String[] args) {
     
    		JFrame frame = new DemoFrame();
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		frame.setSize(400, 400);
    		frame.setLocationRelativeTo(null);
    		frame.setVisible(true);
     
    	}
     
    }
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2016
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2016
    Messages : 25
    Points : 23
    Points
    23
    Par défaut
    C'est génial, et c'est costaud aussi du coup j'ai pas mal de choses à comprendre.

    Question : pourquoi écris-tu
    au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.DispatchKeyEvent()
    ou ?

    je suis en train d'apprendre java en formation et on ne s'est pas arrêté sur les spécificité de Java8.
    Et là où ca me trouble plus c'est qu'en php par exemple c'est ce qu'on utilise pour appeller des méthodes statiques.

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par zhero Voir le message
    Question : pourquoi écris-tu
    au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.DispatchKeyEvent()
    ou ?
    Tu parles de cette instruction KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this::dispatchKeyEvent);C'est justement une spécificité Java 8. On appelle ça une réféfence de méthode.

    La méthode addKeyEventDispatcher de la classe KeyboardFocusManager, type de retour de KeyboardFocusManager.getCurrentKeyboardFocusManager(), prend en paramètre un objet de type KeyEventDispatcher, qui est défini comme une interface dite fonctionnelle, c'est-à-dire une interface à une seule méthode non implémentée.

    Voici le code source de l'interface. On y voit justement une annotation, @FunctionalInterface, qui garanti en quelque sorte, que cette interface n'évoluera pas de manière à avoir d'autres méthodes
    à implémenter :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    package java.awt;
     
    import java.awt.event.KeyEvent;
     
    @FunctionalInterface
    public interface KeyEventDispatcher {
    	boolean dispatchKeyEvent(KeyEvent event);
    }
    Avant Java 8, il fallait faire une implémentation de cette interface pour pouvoir avoir un paramètre à passer à KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(). Donc soit faire une classe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public class MyKeyEventDispatcher implements KeyEventDispatcher {
    	public boolean dispatchKeyEvent(KeyEvent event) {
                     // ici le code à faire
            }
    }
    puis
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher( new MyKeyEventDispatcher() );
    ou encore faire une classe anonyme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher( new KeyEventDispatcher () {
            public boolean dispatchKeyEvent(KeyEvent event) {
                     // ici le code à faire
            }
    } );
    Java 8 introduit la notion d'expressions lambda et la notion de référence de méthode. Ces deux formes d'expressions syntaxiques permettent une implémentation d'interface fonctionnelle avoir moins de chose à écrire (que l'implémentation par classe, anonyme ou pas).

    Par expression lamda, on aurait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(e-> ici le code à exécuter);
    le e représente le paramètre de l'unique méthode, la flêche (->) indique que c'est une expression lambda.
    Dans mon exemple, j'ai fait une méthode (dispatchKeyEvent) pour traiter l'évenement (parce qu'il y plusieurs cas, et que je voulais éviter d'avoir une écriture qui finalement n'était que très ressemblante à l'implémentation de la classe anonyme, donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(e->dispatchKeyEvent(e));
    Dans certain cas, on peut simplifier l'écriture de l'expression lambda on utilisant une référence de méthode :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this::dispatchKeyEvent);
    C'est le :: qui indique qu'il s'agit d'une référence de méthode. Cette expression est équivalente à la précédente (dans le contexte).

    Quant aux deux autres expressions que tu proposes :
    Citation Envoyé par zhero Voir le message
    this.DispatchKeyEvent() ou DispatchKeyEvent() ?
    elles sont tout simplement syntaxiquement incorrectes dans le contexte. La méthode addKeyEventDispatcher() prend un KeyEventDispatcher en paramètre, un objet donc. Pas une méthode. Surtout qu'on ne peut pas passer de méthode en paramètre d'une méthode. Les expressions lambda et références de méthode permettent justement de contourner cette impossiblité, en faisant quelque chose qui du point de vue syntaxique est raccourci par rapport à l'implémentation anonyme qui serait le seul autre moyen de faire quelque chose qui ressemble à un passage de méthode en paramètre.
    A noter, également, de faire attention à la casse : Java y est sensible, ce qui veut dire que DispatchKeyEvent et dispatchKeyEvent, ce n'est pas la même chose.


    Citation Envoyé par zhero Voir le message
    je suis en train d'apprendre java en formation et on ne s'est pas arrêté sur les spécificité de Java8.
    Et là où ca me trouble plus c'est qu'en php par exemple c'est ce qu'on utilise pour appeller des méthodes statiques.
    Les méthodes statiques en Java s'appellent simplement en indiquant le nom de la classe et la méthode :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public class Exemple {
         public static void uneMethodeStatique() {
         }
    }
    L'appel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Exemple.uneMethodeStatique();
    En réalité, on pourrait écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Exemple unExemple = new Exemple();
    unExemple.uneMethodeStatique();
    On ne le fait simplement pas, par convention, pour éviter la confusion que ça peut engendrer (qu'on pourrait penser qu'il s'agit d'une méthode qui agit sur un contexte non statique de l'instance), et d'ailleurs ceci est signalé par une alerte dans les IDE, ou lors de la compilation.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

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

Discussions similaires

  1. [PowerBuilder] Récupérer la main sur une fenêtre modale
    Par jpdar dans le forum Powerbuilder
    Réponses: 3
    Dernier message: 12/06/2006, 14h21
  2. Simuler le clavier sur une fenêtre plein-écran ?
    Par Cracking_Cow dans le forum Windows
    Réponses: 10
    Dernier message: 23/08/2005, 12h20
  3. Réponses: 4
    Dernier message: 25/07/2005, 14h24
  4. Faire défiler un texte sur une fenêtre
    Par Crisanar dans le forum Windows
    Réponses: 15
    Dernier message: 24/11/2004, 23h05
  5. Rendre le curseur invisible sur une fenêtre donnée
    Par Meuhmeuh dans le forum C++Builder
    Réponses: 3
    Dernier message: 22/11/2002, 12h25

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