Andreascopp
Andreascopp

Reputation: 113

How to clear a JTextArea by pressing enter and remain on the same line

I'm trying to clear a JTextArea of 2 rows after pressing enter. I set a KeyListener that triggers when the pressed key is enter; I use setText("") and it clears it but my problem is that it goes to the next line and the text into the area remain made by 2 lines but I want only one line. I also tried to set the caret but it doesn't work, it places the caret at the beginning of the second line. Here's the listener code, I think it's enough because this does all the work, in case you need more code let me know.

private class AscoltatoreKey implements KeyListener{
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode() == KeyEvent.VK_ENTER){  //viene azionato quando viene premuto invio
            String espressione = input.getText().trim();  //prendo il testo dall'area di input
            valutatore.addEspressione(espressione); //aggiungo l'espressione al valutatore
            numeroEspressioni++;
            areaEquazioni.append(numeroEspressioni + ") " + espressione +"\n");  //scrivo l'espressione nella lista delle espressioni
            try{
                areaSoluzioni.append(numeroEspressioni + ") " + valutatore.risolvi() + "\n"); //scrivo l'espressione nella lista delle soluzioni
            }catch (Exception exc){
                areaSoluzioni.append(numeroEspressioni + ") " + "Espressione malformata!" + "\n");
            }
            input.setText(""); //svuoto l'area di input per prepararmi a ricevere la nuova espressione
            input.setCaretPosition(0);
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }
}

Upvotes: 0

Views: 985

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285403

Never add a KeyListener to a JTextComponent such as a JTextArea as this can ruin the underlying function of the text component. Instead use what the Swing library uses when it wants to trap key strokes on a component: use Key Bindings.

For example if you bound the enter key stroke to an Action that cleared the JTextArea, your code would work. In the code below we get the InputMap for the JTextArea for when it has focus:

int condition = JComponent.WHEN_FOCUSED;
InputMap inputMap = textArea.getInputMap(condition);

and also get the JTextArea's ActionMap

ActionMap actionMap = textArea.getActionMap();

then we tie the two maps together, we bind them using the same String constant, here I use the .toString() for my KeyStroke, but any unique (one not also used in the current InputMap) String will do. The action simply clears the JTextArea that caused the action to occur (the source of the Action):

KeyStroke enterKey = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);   
inputMap.put(enterKey, enterKey.toString());
actionMap.put(enterKey.toString(), new AbstractAction() {

    @Override
    public void actionPerformed(ActionEvent e) {
        JTextArea txtArea = (JTextArea) e.getSource();
        txtArea.setText("");
    }
});

My full MCVE example of the above in action:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;

public class ClearTextAreaEg extends JPanel {
    private JTextArea textArea = new JTextArea(10, 20);

    public ClearTextAreaEg() {
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);

        int condition = JComponent.WHEN_FOCUSED;
        InputMap inputMap = textArea.getInputMap(condition);
        ActionMap actionMap = textArea.getActionMap();

        KeyStroke enterKey = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);

        inputMap.put(enterKey, enterKey.toString());
        actionMap.put(enterKey.toString(), new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent e) {
                JTextArea txtArea = (JTextArea) e.getSource();
                txtArea.setText("");
            }
        });

        setLayout(new BorderLayout());
        add(new JScrollPane(textArea));
    }

    private static void createAndShowGui() {
        ClearTextAreaEg mainPanel = new ClearTextAreaEg();

        JFrame frame = new JFrame("ClearTextAreaEg");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

Upvotes: 1

Related Questions