2

for Java Kepler Eclipse and Jtable, I am trying to make it so as when a specific table cell is selected, that cell will work as an editorPane; or have the whole column work as editorPane. When I click a cell on column COMMENTS it enlargens the row but I cant get it to work as an editorPane. My project is actualy very different but I wrote this mini one with the table so you can copy, paste and run it to see exactly what the problem is when you click on a COMMENTS cell.

I tried to make the column an editorPane to begin with like I made the column DONE with checkBox, but it doesnt work or I am doing it wrong. I also tried cellRenderer but I couldnt make that work either.

Whether the whole column works as an editorPane or just the selected cell it doesnt matter, whatever is easier and as long as it works

import javax.swing.*;
import javax.swing.table.*;    
import java.awt.*;
public class JavaTestOne {
    JFrame frmApp;
    private JTable table;
    private JCheckBox checkbox;
    DefaultTableModel model;
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    JavaTestOne window = new JavaTestOne();
                    window.frmApp.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });  
    }
    public JavaTestOne() {  
        initialize();
    }
    private void initialize() {
        frmApp = new JFrame();
        frmApp.getContentPane().setFont(new Font("Tahoma", Font.PLAIN, 13));
        frmApp.setBounds(50, 10, 1050, 650);
        frmApp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frmApp.getContentPane().setLayout(new CardLayout(0, 0));
        frmApp.setTitle("App");
        {
            JScrollPane scrollPane = new JScrollPane();
            scrollPane.setBounds(0, 42, 984, 484);
            frmApp.add(scrollPane);
            {
                table = new JTable();
                table.setFillsViewportHeight(true);
                Object[][] data = {
                        {"I01", "Tom",new Boolean(false), ""},
                        {"I02", "Jerry",new Boolean(false), ""},
                        {"I03", "Ann",new Boolean(false), ""}};
                String[] cols = {"ID","NAME","DONE","COMMENTS"};
                model = new DefaultTableModel(data, cols) {
                    private static final long serialVersionUID = -7158928637468625935L;

                    public Class getColumnClass(int column) {
                        return getValueAt(0, column).getClass();
                    }
                };
                table.setModel(model);
                table.setRowHeight(20);

                table.addMouseListener(new java.awt.event.MouseAdapter() {
                    public void mouseClicked(java.awt.event.MouseEvent evt) {
                        int row = table.rowAtPoint(evt.getPoint());
                        int col = table.columnAtPoint(evt.getPoint());
                        table.setRowHeight(20);
                        if(col==3){
                            table.setRowHeight(row, 100);
                            //this is where I need it to work as an editorPane if it is only for the selected cell
                        }
                    }
                });
                table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
                scrollPane.setViewportView(table);
                checkbox = new JCheckBox("OK");
                checkbox.setHorizontalAlignment(SwingConstants.CENTER);
                checkbox.setBounds(360, 63, 97, 23);
            }
        }
    }
}
Vicki K
  • 23
  • 8
  • +1 for including [MVCE](http://stackoverflow.com/help/mcve). On the other hand Swing is intended to be used with [Layout Managers](http://docs.oracle.com/javase/tutorial/uiswing/layout/using.html) and thus you should avoid methods such as `setBounds()`, `setLocation()`, `setXxxSize()`, because components size and position is responsibility of layout managers. – dic19 Jul 29 '14 at 12:58
  • Thanks for that @dic19 , I took out the 'setBounds()' & 'setLocation()', and it works the same, but i do want the 'setXxxSize()'. Still can you help with my question for cell or column? – Vicki K Jul 29 '14 at 13:13
  • Yes it does work but eventually you will fall in a common pitfall shown in [this answer](http://stackoverflow.com/questions/12529200/non-resizable-window-border-and-positioning/12532237#12532237). For the rest you have useful answers now :) – dic19 Jul 29 '14 at 13:22

2 Answers2

2

Seems you need to implement your own TableCellEditor, read more in tutorial.

For example like that:

 private class CustomEditor extends AbstractCellEditor implements TableCellEditor{

    private JTextPane pane = new JTextPane();
    private JScrollPane scroll = new JScrollPane(pane);
    private int row = -1;

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

    @Override
    public Component getTableCellEditorComponent(JTable table,
            Object value, boolean isSelected, int row, int column) {
        if(this.row != -1)
            table.setRowHeight(this.row, 20);
        this.row = row;
        table.setRowHeight(row, 100);
        pane.setText(value == null ? "" : value.toString());
        return scroll;
    }

}

and then set it as column editor: table.getColumn("COMMENTS").setCellEditor(new CustomEditor());

enter image description here

alex2410
  • 10,904
  • 3
  • 25
  • 41
  • @VickiK , you can try to use `JTextArea` instead of `JTextPane` and use method `textArea.setLineWrap(true);`. – alex2410 Jul 30 '14 at 07:14
2

Another alternative is to display a popup window to edit the cell:

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();
            }
        });
    }

}

Using this approach you don't continually manipulate the row size. You could even customize the code to make the dialog fit the width of the cell and appear below the cell.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • I really liked your answer and it works just fine with the code I have above, but in my actual code the class already extends JDialog and I cant make it work. If there is simple way to make it work with JDialog Class please inform me, otherwise I will go with alex2410 's code which works perfactly with my actual code. Thank you very much!! – Vicki K Jul 29 '14 at 15:21
  • Thank you @alex2410 , your code was very simple to implament with my actual code!But the problem is that when it reaches the side of the cell it just keeps going, it doesnt change line like an editorPane unless you press enter, is there a simple way to care of that? – Vicki K Jul 29 '14 at 15:39
  • @VickiK, `but in my actual code the class already extends JDialog and I cant make it work.` That makes no difference. This code is for creating a custom editor. So all this code (except for the code that creates the GUI) should be in its own class. – camickr Jul 30 '14 at 01:41