2010-01-29 9 views
7

He agregado un keylistener a mi campo JTextArea, pero no se comporta como esperaba.JTextArea nueva línea en shift + enter

inputTextArea.addKeyListener(new KeyAdapter() { 
public void keyPressed(KeyEvent k) { 
    //If the return button is hit, only set to a new line if shift is also down. 
    if(k.getKeyChar() == KeyEvent.VK_ENTER) { 
    if(k.isShiftDown()) { 
    inputTextArea.append(" \n"); 
    } else { 
    //Send The Message... 
    boolean cleanTextField = false; 
    try { 
    sendMessage(inputTextArea.getText()); 
    cleanTextField = true; 
    msgScrollPane.setAutoscrolls(true); 

    JScrollBar vbar = msgScrollPane.getVerticalScrollBar(); 
    if ((vbar.getValue() + vbar.getVisibleAmount()) == vbar.getMaximum()) { 
     msgPane.setCaretPosition(msgDoc.getLength()); 
    } 
    } catch (Exception ex) { 
    ex.printStackTrace(); 
    cleanTextField = false; 
    } finally { 
    if(cleanTextField) { 
     inputTextArea.setText(""); 
    } 
    } 
    } 
    } 
} 
}); 

quiero esto: - Si el botón de retorno es golpeado y el desplazamiento es hacia abajo: añadir una nueva línea. - Si se presiona el botón de retorno y el botón de cambio no está abajo: no hay línea nueva, pero envía.

Ahora se comporta así: - Si presiono el botón de retorno y el cambio está abajo: no se agregó ninguna línea. No pasa nada. - Si presiono el botón de retorno y el desplazamiento no está abajo: enviado, pero si empiezo a escribir nuevamente, comienza en una nueva línea.

¿Alguien sabe cómo hacer lo que quiero?

EDIT:

he intentado algún otro código para detectar si el botón de cambio se ha reducido:

    if((k.getModifiersEx() == KeyEvent.SHIFT_DOWN_MASK) || 
          (k.getModifiers() == KeyEvent.SHIFT_DOWN_MASK)) { 

esto no funciona así

Respuesta

21

Usted puede utilizar el InputMap y ActionMap del JTextArea para mapear las pulsaciones de teclas a las acciones:

private static final String TEXT_SUBMIT = "text-submit"; 
private static final String INSERT_BREAK = "insert-break"; 
... 
private void initialize() { 
    InputMap input = inputTextArea.getInputMap(); 
    KeyStroke enter = KeyStroke.getKeyStroke("ENTER"); 
    KeyStroke shiftEnter = KeyStroke.getKeyStroke("shift ENTER"); 
    input.put(shiftEnter, INSERT_BREAK); // input.get(enter)) = "insert-break" 
    input.put(enter, TEXT_SUBMIT); 

    ActionMap actions = inputTextArea.getActionMap(); 
    actions.put(TEXT_SUBMIT, new AbstractAction() { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      submitText(); 
     } 
    }); 
} 
... 
private void submitText() { 
    // TODO 
} 

La acción original para ENTER - "break insertar" - se utiliza para shift ENTER.

+0

¡Gracias! ¡Esta es la solución que necesitaba! – dododedodonl

+0

+1 por la respuesta menos hacky que he encontrado en línea. – sethro

1

Trate de usar y no keyTyped keyPressed. Creo que KeyPressed te da un evento para el turno y para el enter, mientras que keyTyped te da un evento combinado con un modificador.

+0

Esto no resuelve mis problemas. Ellos son los mismos. – dododedodonl

0

En lugar de realizar las acciones inmediatamente después de recibir el evento, enumerándolas para más tarde mediante su publicación utilizando SwingUtilities.invokeLater(). El código debe ser similar:

if(k.isShiftDown()) { 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
     inputTextArea.append(" \n"); 
     } 
    }); 
} else { 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      //rest of the else body here 
     } 
    }); 

} 

En mi opinión, los problemas que se ven aquí son porque las acciones definidas por la aplicación y acciones internas no están siendo secuenciados adecuadamente, lo que lleva a que suceden vuelve a pintar antes de que el texto ha sido modificado.

+0

Probé este. Mantengo los mismos resultados. Ahora veo que el JTextArea está en un JScrollPane. ¿Podría esto tener un efecto? – dododedodonl

Cuestiones relacionadas