0

I have a custom TableCellEditor/AbstractCellEditor set up so that when the cell is double-clicked or the spacebar is pressed, it enters editing mode.

class TextAreaCellEditor extends AbstractCellEditor implements TableCellEditor {

        JComponent component = new JTextArea();

        @Override
        public boolean isCellEditable(EventObject e) {
            GenInput inp = new GenInput();
            if (super.isCellEditable(e)) {
                if (e instanceof MouseEvent) {
                    MouseEvent me = (MouseEvent) e;
                    return me.getClickCount() >= 2;
                }
                if (e instanceof KeyEvent) {
                    KeyEvent ke = (KeyEvent) e;
                    return ke.getKeyCode() == inp.spacebar; //'inp' is my own class that acts as a reference for keycodes
                }
            }
            return false;
        }
       ...

These both work, and activate StartEdit, which means that the following code is executed next:

@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected,
        int rowIndex, int vColIndex) {

    ((JTextArea) component).setText("");
    ((JTextArea) component).setWrapStyleWord(true);
    ((JTextArea) component).setLineWrap(true);
    ((JTextArea) component).requestFocus();
    ((JTextArea) component).addKeyListener(new KeyListener() {
    ...

Working Part: Regardless of whether or not I include "((JTextArea) component).requestFocus();" , when I double click it full enters editing mode, ie. the caret starts to blink, and when I press 'up' or 'down' the caret moves up and down in the multi-line textbox rather than skipping up or down to the next row.

Problem: However, when I press the spacebar it enters a sort of 'partial' editing mode; The result is that the caret doesn't blink, and while I can type words in the box, if I press 'up'/'down' it will jump to the previous/next row.

What can I do to make the caret appear (ie. enter 'full editing mode' as opposed to the 'partial editing mode' I've described) when I start editing via the spacebar?

Edit: "((JTextArea) component).getCaret().setVisible(true);" makes the caret show up, but doesn't change the fact that it is in a partial editing mode, so I still can't press up/down without losing focus.

  • Based on my limited testing, it works fine. When the `JTable` requests `getTableCellEditorComponent`, the component isn't, obviously, realised on the screen, so calling `requestFocus` has no effect (but you should be calling `requestFocusInWindow` anyway). It also scares me that you're using a `KeyListener` on a `JTextArea` – MadProgrammer Apr 23 '17 at 01:43
  • @MadProgrammer What's the problem with using a keylistener? Is there a better way to get it to end editing on 'enter' when using a JTextArea for a CellEditor? Otherwise it just goes to the next line instead of the next cell without ending editing. I actually tried messing around with the table instead of the textarea, and this solved my problem: "table.setSurrendersFocusOnKeystroke(true);" – Carrot Slat Apr 23 '17 at 01:46
  • [Java KeyListener vs Keybinding](http://stackoverflow.com/questions/23486827/java-keylistener-vs-keybinding) and [KeyListener vs. Key Bindings](http://stackoverflow.com/questions/20873255/keylistener-vs-key-bindings) and [Key bindings vs. key listeners in Java](http://stackoverflow.com/questions/15290035/key-bindings-vs-key-listeners-in-java) – MadProgrammer Apr 23 '17 at 01:52
  • [Can't figure out error with ActionListener](http://stackoverflow.com/questions/33071844/cant-figure-out-error-with-actionlistener/33091886#33091886) - You have to remember, `JTextArea` already has a defined response to the [Enter] key which you know need to overwrite – MadProgrammer Apr 23 '17 at 01:57
  • `'inp' is my own class that acts as a reference for keycodes` - why? Don't reinvent the wheel. There is no need for another class and variable name when you can just use `KeyEvent.VK_SPACE`. – camickr Apr 23 '17 at 02:01

2 Answers2

1

Here's the solution:

table.setSurrendersFocusOnKeystroke(true);

Context:

@Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected,
                int rowIndex, int vColIndex) {

            table.setSurrendersFocusOnKeystroke(true);
            ((JTextArea) component).setText("");
            ((JTextArea) component).setWrapStyleWord(true);
            ((JTextArea) component).setLineWrap(true);
            ((JTextArea) component).setFocusable(true);
0

Works fine for me

import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.EventObject;
import javax.swing.AbstractCellEditor;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                DefaultTableModel model = new DefaultTableModel(10, 1);
                JTable table = new JTable(model);
                table.setDefaultEditor(Object.class, new TextAreaCellEditor());
                table.setRowHeight(20);

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new JScrollPane(table));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    class TextAreaCellEditor extends AbstractCellEditor implements TableCellEditor {

        JTextArea component = new JTextArea();

        @Override
        public boolean isCellEditable(EventObject e) {
            if (super.isCellEditable(e)) {
                if (e instanceof MouseEvent) {
                    MouseEvent me = (MouseEvent) e;
                    return me.getClickCount() >= 2;
                }
                if (e instanceof KeyEvent) {
                    KeyEvent ke = (KeyEvent) e;
                    return ke.getKeyCode() == KeyEvent.VK_SPACE;
                }
            }
            return false;
        }

        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected,
                                                                                                 int rowIndex, int vColIndex) {

            ((JTextArea) component).setText("");
            ((JTextArea) component).setWrapStyleWord(true);
            ((JTextArea) component).setLineWrap(true);
            return  component;
        }

        @Override
        public Object getCellEditorValue() {
            return component.getText();
        }
    }   
}

Maybe something else in your code is messing with it. Consider providing a runnable example which demonstrates your problem. This is not a code dump, but an example of what you are doing which highlights the problem you are having. This will result in less confusion and better responses

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366