Neo
Neo

Reputation: 81

JTextArea. How can I replace text when printing new one?

I created JFrame and JTextArea above it. JTextArea has defaul text "This is text for demo version", that has been set via setText() method.

enter image description here

The goal is to implement this logic: If I start printing text, the old text should be deleted and new one should apper. After that, when new text is printed and if I click "Enter" - new text should be saved into private ArrayList<String> textList

enter image description here

The main question is How to replace old text when I print the first symbol of my text?

I tried to add TestTextArea.this.replaceRange(keyText,0, 30); inside keyReleased(KeyEvent e) {}; (30 it's the last index of default string "This is text for demo version" ). But everytime when I print anything, it causes IllegalArgumentException and seems that old text is still visible on the background.

enter image description here

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;

import static javax.swing.WindowConstants.EXIT_ON_CLOSE;

public class TestTextArea extends JTextArea {

    private String text = "This is text for demo version";
    private ArrayList<String> textList = new ArrayList<>();

    TestTextArea() {
        setBackground(new Color(23, 28, 34, 240));
        setForeground(new Color(6, 200, 109));
        setCaretColor(new Color(6, 200, 109));
        setCaretPosition(0);
        setFont(new Font("Helvetica Neue", Font.BOLD, 16));
        setText(text);
        setLineWrap(true);
        setWrapStyleWord(true);
        setFocusable(true);
        setEnabled(true);
        setEditable(true);
        setVisible(true);

        addKeyListener(new KeyListener() {
            @Override
            public void keyTyped(KeyEvent e) {

            }

            @Override
            public void keyPressed(KeyEvent e) {

            }

            @Override
            public void keyReleased(KeyEvent e) {
                String keyText = KeyEvent.getKeyText(e.getKeyCode());
                TestTextArea.this.replaceRange(keyText,0, 30);
                if (keyText.equals("Enter")) {
                    textList.add(TestTextArea.this.getText());
                }
            }
        });

    }
    public static void main(String []args) {
        JFrame f = new JFrame();

        TestTextArea area = new TestTextArea();
        f.add(area);

        f.setSize(400,200);
        f.setDefaultCloseOperation(EXIT_ON_CLOSE);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

Is there any another way to solve this? I want that after I type the text and press Enter, all the text that I typed is saved. But at the moment it turns out that when you enter the first character, the default text is deleted, but even no one character is saved.

I am sorry, in advance for the possibly not very successful statement of the problem.

Upvotes: 1

Views: 697

Answers (2)

Gilbert Le Blanc
Gilbert Le Blanc

Reputation: 51553

I think I understand your requirements.

  • When the first character is typed, clear the JTextArea and capture the typed text in the JTextArea,

  • When the Enter key is pressed, save the typed text in the List.

This code meets these requirements.

I use a JTextArea. The only reason you extend a Swing component, or any Java class, is to override one or more of the class methods.

I set the size of the JTextArea in the JTextArea constructor. Then I pack the JFrame.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class TextEntryExample implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new TextEntryExample());
    }
    
    private List<String> textList;
    
    private String text;
    
    private JTextArea textArea;
    
    public TextEntryExample() {
        this.text = "This is text for demo version";
        this.textList = new ArrayList<>();
    }

    @Override
    public void run() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        this.textArea = createPrompt();
        f.add(textArea, BorderLayout.CENTER);

        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
    
    private JTextArea createPrompt() {
        JTextArea textArea = new JTextArea(10, 30);
        textArea.addKeyListener(new PromptListener());
        textArea.setBackground(new Color(23, 28, 34, 240));
        textArea.setForeground(new Color(6, 200, 109));
        textArea.setCaretColor(new Color(6, 200, 109));
        textArea.setCaretPosition(0);
        textArea.setFont(new Font("Helvetica Neue", Font.BOLD, 16));
        textArea.setText(text);
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        
        return textArea;
    }
    
    public class PromptListener implements KeyListener {
        
        private boolean entry;
        
        public PromptListener() {
            this.entry = false;
        }

        @Override
        public void keyTyped(KeyEvent e) {
        }

        @Override
        public void keyPressed(KeyEvent event) {
            if (!entry) {
                String oldText = textArea.getText();
                textArea.replaceRange("", 0, oldText.length());
                entry = true;
            }
        }

        @Override
        public void keyReleased(KeyEvent event) {
            if (entry) {
                String keyText = KeyEvent.getKeyText(event.getKeyCode());
                if (keyText.equals("Enter")) {
                    textList.add(textArea.getText());
                    entry = false;
                }
            } 
        }
        
    }

}

Upvotes: 3

John Bayko
John Bayko

Reputation: 1101

This might not be the easiest, but you could replace the document with one that clears the text on the first edit.

I haven't checked, but I think JTextArea uses a DefaultStyledDocument. You can extend that and override the editing methods to check a flag - if it's set, clear the text and clear the flag. I've done something similar this for JTextField (using PlainDocument) - here's how that would look:

public class PromptDocument
    extends PlainDocument
{
    private bool clearOnEdit = false;

    public void insertString(int offset, String str, AttributeSet a)
        throws BadLocationException
    {
        if (clearOnEdit) {
            super.remove(offset, getLength());
            clearOnEdit = false;
        }
        super.insertString(offset, str, a);
    }
    public void remove(int offset, int len)
        throws BadLocationException
    {
        if (clearOnEdit) {
            super.remove(offset, getLength());
            clearOnEdit = false;
        } else {
            super.remove(offset, len);
        }
    }
    public void setClearOnEdit(final boolean clear) {
        clearOnEdit = clear;
    }
}

It should be similar for JTextArea (I haven't tested this, might be missing things). You can just use setDocument() on your JTextArea after you create it.

Upvotes: 1

Related Questions