0

Im rendering a jTextArea inside a jTable cell, when it's rendered, the jTextArea cell uses 'Enter' key as an accept and change of row, and the 'Tab' key goes to the next cell (right one). What I need is to use it as a normal jTextArea, where 'Enter' is a newline, and 'Tab' is a tabulation. I think that there's some properties to be set, but I don't know which ones.

Here's the code I'm using:

    //Renderer

    public class TableCellLongTextRenderer extends JTextArea implements TableCellRenderer{  

    @Override  

    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,   boolean hasFocus, int row, int column) {  
        this.setText((String)value);  
        this.setWrapStyleWord(true);                      
        this.setLineWrap(true);     


        //set the JTextArea to the width of the table column  
        setSize(table.getColumnModel().getColumn(column).getWidth(),getPreferredSize().height);  
        if (table.getRowHeight(row) != getPreferredSize().height) {  
            //set the height of the table row to the calculated height of the JTextArea  
            table.setRowHeight(row, getPreferredSize().height);  
        }  
        return this;  
    }
}

Thanks in advance.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Oscar
  • 21
  • 3

2 Answers2

2

Well after some searching, I finally got it, just copied some code from another answer, and used it in my example, heres the final code for anyone who needs a table with editable cells.

class TextAreaCellRenderer implements TableCellRenderer {

    private JTextArea textArea = new JTextArea();

    public TextAreaCellRenderer() {
        super();
        textArea.setLineWrap(true);
        textArea.setBorder(BorderFactory.createEmptyBorder(1, 5, 1, 5));
    }

    @Override
    public Component getTableCellRendererComponent(
            JTable table, Object value, boolean isSelected, boolean hasFocus,
            int row, int column) {
        if (isSelected) {
            textArea.setForeground(table.getSelectionForeground());
            textArea.setBackground(table.getSelectionBackground());
        } else {
            textArea.setForeground(table.getForeground());
            textArea.setBackground(table.getBackground());
        }
        textArea.setFont(table.getFont());
        textArea.setText((value == null) ? "" : value.toString());
        return textArea;
    }
}

class TextAreaCellEditor implements TableCellEditor {

    private final JScrollPane scroll;
    private JTextArea textArea = new JTextArea();

    public TextAreaCellEditor() {
        scroll = new JScrollPane(textArea);
        scroll.setBorder(BorderFactory.createEmptyBorder());
        //scroll.setViewportBorder(BorderFactory.createEmptyBorder());
        textArea.setLineWrap(true);
        textArea.setBorder(BorderFactory.createEmptyBorder(1, 5, 1, 5));
        KeyStroke enter = KeyStroke.getKeyStroke(
                KeyEvent.VK_ENTER, InputEvent.CTRL_MASK);
        textArea.getInputMap(JComponent.WHEN_FOCUSED).put(enter, new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                stopCellEditing();
            }
        });
    }

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

    @Override
    public Component getTableCellEditorComponent(
            JTable table, Object value, boolean isSelected, int row, int column) {
        System.out.println("2. getTableCellEditorComponent");
        textArea.setFont(table.getFont());
        textArea.setText((value != null) ? value.toString() : "");
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                textArea.setCaretPosition(textArea.getText().length());
                textArea.requestFocusInWindow();
                System.out.println("4. invokeLater: getTableCellEditorComponent");
            }
        });
        return scroll;
    }

    @Override
    public boolean isCellEditable(final EventObject e) {
        if (e instanceof MouseEvent) {
            return ((MouseEvent) e).getClickCount() >= 2;
        }
        System.out.println("1. isCellEditable");
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                if (e instanceof KeyEvent) {
                    KeyEvent ke = (KeyEvent) e;
                    char kc = ke.getKeyChar();
                    if (Character.isUnicodeIdentifierStart(kc)) {
                        textArea.setText(textArea.getText() + kc);
                        System.out.println("3. invokeLater: isCellEditable");
                    }
                }
            }
        });
        return true;
    }

    //Copid from AbstractCellEditor
    protected EventListenerList listenerList = new EventListenerList();
    transient protected ChangeEvent changeEvent = null;

    @Override
    public boolean shouldSelectCell(EventObject e) {
        return true;
    }

    @Override
    public boolean stopCellEditing() {
        fireEditingStopped();
        return true;
    }

    @Override
    public void cancelCellEditing() {
        fireEditingCanceled();
    }

    @Override
    public void addCellEditorListener(CellEditorListener l) {
        listenerList.add(CellEditorListener.class, l);
    }

    @Override
    public void removeCellEditorListener(CellEditorListener l) {
        listenerList.remove(CellEditorListener.class, l);
    }

    public CellEditorListener[] getCellEditorListeners() {
        return listenerList.getListeners(CellEditorListener.class);
    }

    protected void fireEditingStopped() {
        // Guaranteed to return a non-null array
        Object[] listeners = listenerList.getListenerList();
// Process the listeners last to first, notifying
        // those that are interested in this event
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == CellEditorListener.class) {
                // Lazily create the event:
                if (changeEvent == null) {
                    changeEvent = new ChangeEvent(this);
                }
                ((CellEditorListener) listeners[i + 1]).editingStopped(changeEvent);
            }
        }
    }

    protected void fireEditingCanceled() {
        // Guaranteed to return a non-null array
        Object[] listeners = listenerList.getListenerList();
// Process the listeners last to first, notifying
        // those that are interested in this event
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == CellEditorListener.class) {
                // Lazily create the event:
                if (changeEvent == null) {
                    changeEvent = new ChangeEvent(this);
                }
                ((CellEditorListener) listeners[i + 1]).editingCanceled(changeEvent);
            }
        }
    }
}

Only have to copy those 2 classes, and use it in your table, like this:

    'jTableName'.getColumnModel().getColumn('number of column you need to set editable').setCellRenderer(new 'principal class name'.TextAreaCellRenderer()); 
    'jTableName'.getColumnModel().getColumn('number of column you need to set editable').setCellEditor(new 'principal class name'.TextAreaCellEditor());

Just change the commented parts, and that's it, hope it helps someone like it helped me, I used this link as base. Custom CellEditor with JScrollPane - start editing issue

Community
  • 1
  • 1
Oscar
  • 21
  • 3
1

Not sure I understand the question. A renderer does not accept key strokes. It is the editor that allows you to change the data in the cell.

Doesn't answer your question but here is an example of using a JTextArea as a popup editor for the cell, which may or may not work for your requirement:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;

/*
 * The editor button that brings up the dialog.
 */
//public class TablePopupEditor extends AbstractCellEditor
public class TablePopupEditor extends DefaultCellEditor
    implements TableCellEditor
{
    private PopupDialog popup;
    private String currentText = "";
    private JButton editorComponent;

    public TablePopupEditor()
    {
        super(new JTextField());

        setClickCountToStart(1);

        //  Use a JButton as the editor component

        editorComponent = new JButton();
        editorComponent.setBackground(Color.white);
        editorComponent.setBorderPainted(false);
        editorComponent.setContentAreaFilled( false );

        // Make sure focus goes back to the table when the dialog is closed
        editorComponent.setFocusable( false );

        //  Set up the dialog where we do the actual editing

        popup = new PopupDialog();
    }

    public Object getCellEditorValue()
    {
        return currentText;
    }

    public Component getTableCellEditorComponent(
        JTable table, Object value, boolean isSelected, int row, int column)
    {

        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                popup.setText( currentText );
//              popup.setLocationRelativeTo( editorComponent );
                Point p = editorComponent.getLocationOnScreen();
                popup.setLocation(p.x, p.y + editorComponent.getSize().height);
                popup.show();
                fireEditingStopped();
            }
        });

        currentText = value.toString();
        editorComponent.setText( currentText );
        return editorComponent;
    }

    /*
    *   Simple dialog containing the actual editing component
    */
    class PopupDialog extends JDialog implements ActionListener
    {
        private JTextArea textArea;

        public PopupDialog()
        {
            super((Frame)null, "Change Description", true);

            textArea = new JTextArea(5, 20);
            textArea.setLineWrap( true );
            textArea.setWrapStyleWord( true );
            KeyStroke keyStroke = KeyStroke.getKeyStroke("ENTER");
            textArea.getInputMap().put(keyStroke, "none");
            JScrollPane scrollPane = new JScrollPane( textArea );
            getContentPane().add( scrollPane );

            JButton cancel = new JButton("Cancel");
            cancel.addActionListener( this );
            JButton ok = new JButton("Ok");
            ok.setPreferredSize( cancel.getPreferredSize() );
            ok.addActionListener( this );

            JPanel buttons = new JPanel();
            buttons.add( ok );
            buttons.add( cancel );
            getContentPane().add(buttons, BorderLayout.SOUTH);
            pack();

            getRootPane().setDefaultButton( ok );
        }

        public void setText(String text)
        {
            textArea.setText( text );
        }

        /*
        *   Save the changed text before hiding the popup
        */
        public void actionPerformed(ActionEvent e)
        {
            if ("Ok".equals( e.getActionCommand() ) )
            {
                currentText = textArea.getText();
            }

            textArea.requestFocusInWindow();
            setVisible( false );
        }
    }

    private static void createAndShowUI()
    {
        String[] columnNames = {"Item", "Description"};
        Object[][] data =
        {
            {"Item 1", "Description of Item 1"},
            {"Item 2", "Description of Item 2"},
            {"Item 3", "Description of Item 3"}
        };

        JTable table = new JTable(data, columnNames);
        table.getColumnModel().getColumn(1).setPreferredWidth(300);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JScrollPane scrollPane = new JScrollPane(table);

        // Use the popup editor on the second column

        TablePopupEditor popupEditor = new TablePopupEditor();
        table.getColumnModel().getColumn(1).setCellEditor( popupEditor );

        JFrame frame = new JFrame("Popup Editor Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new JTextField(), BorderLayout.NORTH);
        frame.add( scrollPane );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }

}
camickr
  • 321,443
  • 19
  • 166
  • 288