Search code examples
javaswingjtextarea

Command + Backspace functionality in JTextArea


I have a small text editor that I made in Java Swing with JTextArea.

enter image description here

I want to implement the following:
When the user presses Command+Backspace I want to remove all the text from the beginning of the line up to the cursor. How to implement this? I tried using KeyListeners but it doesn't work.

For example (before user presses Command+Backspace) ...

before

Result (after user presses Command+Backspace) ...

after

My code (Not 100% exact compared to the image):

import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class Main{
    static JFrame frame = new JFrame();
    static JTextArea textArea = new JTextArea();
    static JScrollPane scrollPane = new JScrollPane(textArea);

    public static void main(String[] args) throws BadLocationException {
        frame.setTitle("Untitled");
        addComponentsToFrame();
        textArea.addKeyListener(new KeyListener(){
            @Override
            public void keyTyped(KeyEvent e) {
                if(e.getKeyCode() == (Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx() | KeyEvent.VK_BACK_SPACE)){
                    System.out.println("Delete"); //Placeholder
                }
            }
            @Override
            public void keyPressed(KeyEvent e) {}
            @Override
            public void keyReleased(KeyEvent e) {}
        });
    }
    
    public static void addComponentsToFrame(){
        scrollPane.setAutoscrolls(true);
        frame.add(scrollPane);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500, 500);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

For now when I have placed a print Statement as a place holder, since I don't know how to delete all the words from the beginning of the line up to the cursor (i.e. the logic).


Solution

  • Credits: @Abra

    Solution:

    import java.awt.BorderLayout;
    import java.awt.EventQueue;
    import java.awt.event.ActionEvent;
    import java.awt.event.InputEvent;
    import java.awt.event.KeyEvent;
    
    import javax.swing.AbstractAction;
    import javax.swing.ActionMap;
    import javax.swing.InputMap;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.KeyStroke;
    import javax.swing.text.BadLocationException;
    import java.awt.Toolkit;
    public class TestSamplePrograms {
        private JTextArea  textarea;
    
        private void buildAndShowGui() {
            JFrame frame = new JFrame("Untitled");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(createTextArea(), BorderLayout.CENTER);
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    
        private JScrollPane createTextArea() {
            textarea = new JTextArea(20, 60);
            InputMap im = textarea.getInputMap();
            KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx());
            im.put(ks, "del2EoL");
            ActionMap am = textarea.getActionMap();
            am.put("del2EoL", new Delete2EOL());
            JScrollPane pane = new JScrollPane(textarea);
            return pane;
        }
    
        @SuppressWarnings("serial")
        private class Delete2EOL extends AbstractAction {
    
            @Override
            public void actionPerformed(ActionEvent e) {
                int caretOffset = textarea.getCaretPosition();
                int lineNumber = 0;
                try {
                    lineNumber = textarea.getLineOfOffset(caretOffset);
                    int startOffset = textarea.getLineStartOffset(lineNumber);
                    int endOffset = textarea.getLineEndOffset(lineNumber);
                    textarea.replaceRange("", startOffset, endOffset);
                } catch (BadLocationException ex) {
                    throw new RuntimeException(ex);
                }
            }
        }
    
        public static void main(String[] args) {
            EventQueue.invokeLater(() -> new TestSamplePrograms().buildAndShowGui());
        }
    }