web-dev-qa-db-fra.com

En cliquant par programme sur un bouton d'interface graphique dans Java Swing

Comment pourrais-je cliquer par programmation sur un JButton Swing de manière à enregistrer tous les événements d'action/souris pertinents et à être visibles par l'utilisateur (c'est-à-dire qu'ils verraient le bouton enfoncé comme s'ils le faisaient réellement)?

Le bouton est dans la même application que je cours; Je n'essaie pas de contrôler un bouton dans une autre application. Je suppose que je pourrais directement injecter des événements dans la file d'attente, mais je préférerais éviter cette approche si possible, et le faire de cette manière ne produirait pas de clic visible.

Je vois que la classe Java.awt.Robot propose des méthodes pour déplacer la souris et cliquer sur la souris, mais pas pour la faire cliquer sur un bouton particulier.

50
Gigatron

Avez-vous essayé d'utiliser doClick () ?

90
JasCav

Si doClick() n'est pas ce que vous voulez, vous pouvez déplacer la souris vraiment sur le bouton et appuyer dessus:

public void click(AbstractButton button, int millis) throws AWTException
{
    Point p = button.getLocationOnScreen();
    Robot r = new Robot();
    r.mouseMove(p.x + button.getWidth() / 2, p.y + button.getHeight() / 2);
    r.mousePress(InputEvent.BUTTON1_MASK);
    try { Thread.sleep(millis); } catch (Exception e) {}
    r.mouseRelease(InputEvent.BUTTON1_MASK);
}
9
Martijn Courteaux

Même si le demandeur était satisfait de button.doClick(), je recherchais quelque chose comme ce qui se passe après la définition d’un mnémonique, c’est-à-dire avec button.setMnemonic(KeyEvent.VK_A). Vous pouvez en fait appuyer sur ALT + A sans que rien ne se passe (sauf le changement visuel). Et lors du relâchement de la touche A (avec ou sans ALT), le bouton déclenche un ActionEvent.

J'ai découvert que je pouvais obtenir le ButtonModel (voir API Java 8 ) avec button.getModel(), puis appuyer sur le bouton avec model.setPressed(true); model.setArmed(true); (les deux sont modifiés par des mnémoniques) et le relâcher visuellement en définissant les deux sur false. Et lorsque model.setPressed(false) est appelé alors que le bouton est à la fois enfoncé et armé, le bouton déclenche automatiquement un ActionEvent (l'appel de model.setArmed(false) modifie uniquement le bouton de manière visuelle).

[Extrait de la documentation de l'API Java de ButtonModel] Un bouton est déclenché et un ActionEvent est déclenché lorsque la souris est relâchée alors que le modèle est armé [...]

Pour que l'application réagisse aux appuis sur les touches lorsque le bouton est visible (sans que la fenêtre qui le contient ou le bouton doive être propriétaire de la focalisation, c'est-à-dire lorsqu'un autre composant de la fenêtre est focalisé), j'ai utilisé les raccourcis clavier (voir le Tutoriel Java officiel ).

Code de travail: Appuyez sur SHIFT + A pour appuyer visuellement sur le bouton (contrairement à ALT avec la touche après que la mnémonique est réglée avec button.setMnemonic()). Et relâchez la touche pour imprimer la commande d'action ("bouton") sur la console.

// MnemonicCode.Java
import javax.swing.*;
import Java.awt.event.*;

public class MnemonicCode extends JFrame
{
  public MnemonicCode(int keyCode)
  {
    JButton button = new JButton("button");

    getContentPane().add(button);
    addMnemonicToButton(button,keyCode);
    button.addActionListener(new ActionListener () {
      public void actionPerformed(ActionEvent e)
      {
        System.out.println(e.getActionCommand());
      }
    });

    pack();
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    setVisible(true);
  }

  public static void main(String[] args) throws Exception
  {
    MnemonicCode bp = new MnemonicCode(KeyEvent.VK_A);
  }

  void addMnemonicToButton(JButton button,int keyCode)
  {
    int shiftMask = InputEvent.SHIFT_DOWN_MASK;

    // signature: getKeyStroke(int keyCode, int modifiers, boolean onKeyRelease)
    KeyStroke keyPress = KeyStroke.getKeyStroke(keyCode,shiftMask,false);
    KeyStroke keyReleaseWithShift = KeyStroke.getKeyStroke(keyCode,shiftMask,true);

    // get maps for key bindings
    InputMap inputMap = button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
    ActionMap actionMap = button.getActionMap();

    // add key bindings for pressing and releasing the button
    inputMap.put(keyPress,"press"+keyCode);
    actionMap.put("press"+keyCode, new ButtonPress(button));

    inputMap.put(keyReleaseWithShift,"releaseWithShift"+keyCode);
    actionMap.put("releaseWithShift"+keyCode, new ButtonRelease(button));

    ///*
    // add key binding for releasing SHIFT before A
    // if you use more than one modifier it gets really messy
    KeyStroke keyReleaseAfterShift = KeyStroke.getKeyStroke(keyCode,0,true);
    inputMap.put(keyReleaseAfterShift,"releaseAfterShift"+keyCode);
    actionMap.put("releaseAfterShift"+keyCode, new ButtonRelease(button));
    //*/
  }

  class ButtonPress extends AbstractAction
  {
    private JButton button;
    private ButtonModel model;
    ButtonPress(JButton button)
    {
      this.button = button;
      this.model = button.getModel();
    }

    public void actionPerformed(ActionEvent e)
    {
      // visually press the button
      model.setPressed(true);
      model.setArmed(true);

      button.requestFocusInWindow();
    }
  }

  class ButtonRelease extends AbstractAction
  {
    private ButtonModel model;
    ButtonRelease(JButton button)
    {
      this.model = button.getModel();
    }

    public void actionPerformed(ActionEvent e)
    {
      if (model.isPressed()) {
        // visually release the button
        // setPressed(false) also makes the button fire an ActionEvent
        model.setPressed(false);
        model.setArmed(false);
      }
    }
  }
}
3
mkdrive2

Vous pouvez toujours le simuler en lançant un événement d'action avec lui comme source.

http://download.Oracle.com/javase/6/docs/api/Java/awt/event/ActionEvent.html

Pour le déclencher, créez l'événement action ci-dessus, et écoutez le programme d'écoute que vous souhaitez appeler

ActionEvent e = new ActionEvent(myButton,1234,"CommandToPeform");
myListener.actionPerformed(e);
2
corsiKa

De: http://download.Oracle.com/javase/6/docs/api/javax/swing/JButton.html

/**
 * Click a button on screen
 *
 * @param button Button to click
 * @param millis Time that button will remain "clicked" in milliseconds
 */
public void click(AbstractButton button, int millis) {
   b.doClick(millis);
}
1
Michael K

Basé sur la réponse de @ Courteaux, cette méthode clique sur la première cellule d'une JTable:

private void clickFirstCell() {
    try {
        jTable1.changeSelection(0, 0, false, false);
        Point p = jTable1.getLocationOnScreen();
        Rectangle cellRect = jTable1.getCellRect(0, 0, true);
        Robot r = new Robot();
        Point mouse = MouseInfo.getPointerInfo().getLocation();
        r.mouseMove(p.x + cellRect.x + cellRect.width / 2, 
                p.y + cellRect.y + cellRect.height / 2);
        r.mousePress(InputEvent.BUTTON1_MASK);
        try {
            Thread.sleep(50);
        } catch (Exception e) {
        }
        r.mouseRelease(InputEvent.BUTTON1_MASK);
        r.mouseMove(mouse.x, mouse.y);
    } catch (AWTException ex) {
    }
}
0
user586399