2011-02-24 17 views
47

haciendo clic en un Swing JButton de forma que registre todos los eventos de acción/mouse relevantes y sea visible para el usuario (es decir, ellos verían el botón presionado como si en realidad lo hicieron clic)?Haciendo clic en un botón de la GUI en Java Swing

El botón está en la misma aplicación que estoy ejecutando; No estoy tratando de controlar un botón en otra aplicación. Supongo que podría inyectar directamente eventos en la cola, pero preferiría evitar ese enfoque si fuera posible, y hacerlo de esa manera no mostraría un clic visible.

Veo que la clase java.awt.Robot ofrece métodos para mover el mouse y hacer clic con el mouse, pero no para hacer que haga clic en un botón en particular.

+0

posible duplicado de (http: // stackoverflow. com/questions/4753004/how-do-i-programtically-send-actionevent-to-jbutton) – OscarRyz

Respuesta

87

¿Ha intentado utilizar doClick()?

+1

¡Parece que doClick() hará el trabajo! Debería haberlo notado antes. Supongo que me lo perdí porque no está definido directamente en JButton, se hereda de AbstractButton. – Gigatron

+4

@Gigatron - Sí. La abstracción a veces puede dificultar saber qué hay disponible para usted (especialmente si no hay una buena documentación, gracias a Dios por JavaDocs). ¡Me alegro de poder ayudar! – JasCav

+7

Quizás 'click()' o 'press()' hubieran sido mejores nombres –

9

Si doClick() no es lo que se desea es, puede mover el ratón realmente al botón y presiona:

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); 
} 
+0

Ese es el enfoque en el que estaba pensando anteriormente, pero sentí que tenía que haber una solución más simple ... . y de hecho existe la solución simple de doClick(). – Gigatron

+0

De esta manera está seguro, registradores de teclas o incluso mejor: los moueloggers también habrán atrapado este evento: D –

+1

Ya existe un método de retraso() de la clase Robot que hace la pausa. –

2

pesar de que el autor de la pregunta estaba satisfecho con button.doClick() , Estaba buscando algo así como lo que sucede después de configurar un mnemónico, es decir, con button.setMnemonic(KeyEvent.VK_A). Puedes mantener presionado ALT + A sin que suceda nada (excepto el cambio visual). Y al soltar la tecla A (con o sin ALT), el botón dispara un ActionEvent.

He descubierto que puedo conseguir el ButtonModel (ver Java 8 API) con button.getModel(), a continuación, pulse el botón visualmente con model.setPressed(true); model.setArmed(true); (ambos se intercambien por mnemotécnicos), y suelte el botón visualmente mediante el establecimiento tanto a false. Y cuando se llama al model.setPressed(false) mientras el botón está presionado y armado, el botón dispara un ActionEvent automáticamente (llamando al model.setArmed(false) solo cambia el botón visualmente).

[Presupuesto de ButtonModel Java documentación de la API] Un botón se activa, y un ActionEvent se dispara, cuando se suelta el ratón mientras que el modelo está armado [...]

Para hacer que la la aplicación reacciona a la pulsación de teclas cuando el botón está visible (sin la ventana que lo contiene o el botón que necesita ser el propietario del foco, es decir, cuando se enfoca otro componente de la ventana) Utilicé enlaces de teclas (consulte Official Java Tutorial).

Código de trabajo: Presione MAYÚS + A para apretar visualmente el botón (a diferencia de presionar ALT con la tecla después de que el mnemónico se establece con button.setMnemonic()). Y suelte la tecla para imprimir el comando de acción ("botón") en la consola.

// 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); 
     } 
    } 
    } 
} 
0

Sobre la base de @ respuesta de Courteaux, este método hace clic en la primera celda de un JTable: [? ¿Cómo programáticamente envío ActionEvent a JButton]

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) { 
    } 
} 
Cuestiones relacionadas