Intercepter des frappes composées de touches et utiliser des polices de caractères

     

alt : l'applet n'est pas visible par votre navigateur (dans le menu Outils, Modules complémentaires, activer le plugin Java(TM) Platform SE 6 U32 6.0.320.5 s'il est désactivé)
Le bouton droit est le bouton droit de la souris.

On peut intercepter comme nous l'avons vu dans l'exemple précédent les frappes sur les touches alphabétiques ou numériques. On peut aussi intercepter l'utilisation d'associations de ces touches avec des touches modificatrices ("ctrl", "shift", "meta" et "alt"ctrl) ou avec les boutons enfoncés de la souris. Toutes les touches du clavier peuvent aussi être utilisées, en particulier les touches de fonction ; les touches sont identifiées par des constantes analogues à celles que vous pouvez voir dans le code de notre exemple (VK_R pour le r..., VK_BACK_SPACE, VK_TAB, VK_COMMA, VK_F3, VK_UP, VK_PAGE_UP, VK_HOME, VK_ESCAPE...) ; vous pouvez consulter l'ensemble de ces constantes dans la documentation de la classe java.awt.event.KeyEvent.

Voici une illustration donnant quelques précisions teminologiques en anglais concernant diférentes mesures liées aux polices de caractères.


Le "leading" correspond à un simple interligne. Les méthodes getHeight,getLeading, getAscent et getDescent de la classe java.awt.FontMetrics permettent de connaître les valeurs correspondantes ; la méthode getSize() de la classe java.awt.Font permet de retrouver la taille de la police.

On aurait pu aussi utiliser un JTextArea ou des JLabel(s) pour la liste des indications ; ce serait en fait plus simple que d'utiliser la méthode drawString comme on le fait ci-dessous. On donne après le code ci-dessous des programmes correspondant à ce deux autres solutions.

Voici un programme correspondant à l'applet que vous pouvez apercevoir.

import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Dimension;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.event.InputEvent;

class Indication extends JPanel {
int h;
Indication() {
int hauteur, largeur;
Font font = new Font("TimesRoman", Font.BOLD|Font.ITALIC,14);
FontMetrics ft = getFontMetrics(font);
h = ft.getHeight();
largeur = ft.stringWidth("bouton gauche + b pour voir un disque bleu ");
setPreferredSize(new Dimension(largeur, 6*h + 25));
setFont(font);
}

public void paintComponent(Graphics g) {
int x = 10, y = 40;

g.drawString(" r pour voir un cercle rouge", x, y);
y += h;
g.drawString(" CTRL + r pour voir un disque rouge", x, y);
y += h;
g.drawString(" b pour voir un cercle bleu", x, y);
y += h;
g.drawString(" bouton droit + b pour voir un disque bleu", x, y);
y += h;
g.drawString(" barre d'espace pour descendre le cercle", x, y);
y += h;
g.drawString(" touche \"arriere\" pour repositionner le cercle", x, y);
}
}

class Ardoise extends JPanel {
private Color couleur = Color.BLUE;
private boolean plein = false;
private int hauteur = 20;

Ardoise() {
setPreferredSize(new Dimension(250, 200));
}

public void paintComponent(Graphics g) {
int largeur = getSize().width;

super.paintComponent(g);
g.setColor(couleur);
if (plein) g.fillOval((largeur - 100)/2, hauteur, 100, 100);
else g.drawOval((largeur - 100)/2, hauteur, 100, 100);
}
void setCouleur(Color couleur) {
this.couleur = couleur;
repaint();
}

void setPlein(boolean valeur) {
plein = valeur;
repaint();
}

void setHauteur(int valeur) {
hauteur = valeur;
repaint();
}
}

public class Touches2 extends JFrame implements KeyListener {
Ardoise ardoise = new Ardoise();
Touches2() {
super("Essai des touches");
add(new Indication(), BorderLayout.NORTH);
add(ardoise, BorderLayout.CENTER);
addKeyListener(this);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowOpened(WindowEvent e) {
requestFocus();
}
});
pack();
setVisible(true);
}

public void keyPressed(KeyEvent evt) {
int code = evt.getKeyCode();

if (code == KeyEvent.VK_R) {
ardoise.setCouleur(Color.RED);
if (evt.isControlDown()) ardoise.setPlein(true);
else ardoise.setPlein(false);
}
else if (code == KeyEvent.VK_B) {
ardoise.setCouleur(Color.BLUE);
if ((evt.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0) ardoise.setPlein(true);
else ardoise.setPlein(false);
}
else if (code == KeyEvent.VK_SPACE) ardoise.setHauteur(80);
else if (code == KeyEvent.VK_BACK_SPACE) ardoise.setHauteur(20);
}

public void keyTyped(KeyEvent evt) {}
public void keyReleased(KeyEvent evt) {}
}

class EssaiTouches2 {
public static void main(String[] arg) {
new Touches2();
}
}

Vous pouvez voir :

  • le code en java l'application que vous voyez aussi sur cette page.
  • le code de l'applet.
  • le code en java l'application en utilisant un JTextArea.
  • le code en java l'application en utilisant des JLabel(s).
    FontMetrics ft = getFontMetrics(font) : cette méthode de la classe Component permet de prendre différentes mesures sur la police de caractères indiquée en paramètre.
    ft.getHeight() : cette méthode de la classe FontMetrics donne la hauteur nécessaire entre une ligne et la ligne suivante.
    ft.stringWidth("bouton gauche + b pour voir un disque bleu "); : permet de mesurer le nombre de pixels nécessaire en largeur pour écrire, avec la fonte ft, la chaîne de caractères indiquée en paramètre.
    evt.isControlDown() : méthode de la classe abstraite java.awt.event.InputEvent dont hérite la classe keyEvent qui retourne true ou false selon que la touche "ctrl" est enfoncée ou non.
    evt.getModifiersEx() : méthode de la classe InputEvent (qui, améliore la méthode getModifiers), dont héritent les classes KeyEvent et MouseEvent, qui renvoie un int décrivant les touches de modification (parmi "ctrl", "shift", "meta", "alt", "alt graph") et les boutons de la souris éventuellement utilisés. À chacune de ces touches ou chacun de ces boutons correspond une constante qui est une puissance de 2 ; l'entier renvoyé par la méthode getModifiersEx est la somme des constantes correspondant aux touches ou boutons appuyés. Supposons que l'utilisateur appuie à la fois sur le bouton de droite de la souris et sur la touche "ctrl" (touche de contrôle) ; au bouton droit de la souris correspond la constante InputEvent.BUTTON3_DOWN_MASK qui vaut 4096 (écriture binaire 1000000000000) ; à la touche "ctrl" correspond la constante InputEvent.CTRL_DOWN_MASK qui vaut 128 (écriture binaire 10000000) ; la méthode getModifiersEx renvoie dans notre cas la somme de 4096 et de 128, c'est- à-dire 4224, qui s'écrit 1000010000000 en binaire : un "1" pour le bouton de droite de la souris et un "1" pour la touche "ctrl".
    InputEvent.BUTTON3_DOWN_MASK : : cette constante fait partie d'un ensemble de constantes où on trouve aussi BUTTON1_DOWN_MASK, BUTTON2_DOWN_MASK, SHIFT_DOWN_MASK, CTRL_DOWN_MASK, ALT_DOWN_MASK, ALT_DOWN_GRAPH_MASK. Considérons l'expression :
        evt.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK ;
    Rappelons que la constante BUTTON3_DOWN_MASK vaut 4096. L'opérateur "&" est un "et" bit à bit ; il faut pour l'évaluer écrire les deux opérandes en binaire ; si, comme dans l'exemple ci-dessus, on a appuyé sur le bouton droit de la souris et sur la touche de contrôle, le calcul effectué est : 1000010000000 & 1000000000000, dont la valeur écrite en binaire est 1000000000000, et donc non nulle. Le résultat est non nul si et seulement si on appuie sur le bouton droit de la souris.

    © Irène Charon, Télécom-ParisTech 2011