简体   繁体   中英

How to select all text in JTable cell when editing

I would like to have the editor in my editable JTables select all text in the cell when starting to edit. I have tried a couple of things that all revolve around calling JTextComponent.selectAll() on the component that is returned from the TableCellEditor.getTableCellEditorComponent method. None of the things I tried worked.

In my latest attempt, I altered the SimpleTableDemo class from the Swing tutorial to use a custom TableCellEditor that calls the selectAll method. In the debugger I can see that the selectAll() method is being called, but the table still goes into edit mode without selecting the text in the cell (or perhaps the selection is being cleared before display). That code is below. Can anybody tell me where I'm going wrong?

import javax.swing.DefaultCellEditor;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.text.JTextComponent;


import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;


public class SimpleTableDemo extends JPanel {
    private boolean DEBUG = false;


    public SimpleTableDemo() {
        super(new GridLayout(1, 0));

        String[] columnNames = {"First Name",
                                "Last Name",
                                "Sport",
                                "# of Years",
                                "Vegetarian"};

        Object[][] data = {
                {"Kathy", "Smith", "Snowboarding", new Integer(5), new Boolean(false)},
                {"John", "Doe", "Rowing", new Integer(3), new Boolean(true)},
                {"Sue", "Black", "Knitting", new Integer(2), new Boolean(false)},
                {"Jane", "White", "Speed reading", new Integer(20), new Boolean(true)},
                {"Joe", "Brown", "Pool", new Integer(10), new Boolean(false)}
        };

        final JTable table = new SelectingTable(data, columnNames);
        table.setPreferredScrollableViewportSize(new Dimension(500, 70));
        table.setFillsViewportHeight(true);

        if (DEBUG) {
            table.addMouseListener(new MouseAdapter() {
                public void mouseClicked(MouseEvent e) {
                    printDebugData(table);
                }
            });
        }

        //Create the scroll pane and add the table to it.
        JScrollPane scrollPane = new JScrollPane(table);

        //Add the scroll pane to this panel.
        add(scrollPane);
    }

    private void printDebugData(JTable table) {
        int numRows = table.getRowCount();
        int numCols = table.getColumnCount();
        javax.swing.table.TableModel model = table.getModel();

        System.out.println("Value of data: ");
        for (int i = 0; i < numRows; i++) {
            System.out.print("    row " + i + ":");
            for (int j = 0; j < numCols; j++) {
                System.out.print("  " + model.getValueAt(i, j));
            }
            System.out.println();
        }
        System.out.println("--------------------------");
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("SimpleTableDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        SimpleTableDemo newContentPane = new SimpleTableDemo();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }


    class SelectingTable extends JTable {
        public SelectingTable(Object[][] data, String[] columnNames) {
            super(data, columnNames);
            TableColumnModel model = super.getColumnModel();
            for (int i = 0; i < super.getColumnCount(); i++) {
                TableColumn tc = model.getColumn(i);
                tc.setCellEditor(new SelectingEditor(new JTextField()));
            }
        }

        class SelectingEditor extends DefaultCellEditor {

            public SelectingEditor(JTextField textField) {
                super(textField);
            }

            public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
                Component c = super.getTableCellEditorComponent(table, value, isSelected, row, column);
                if (c instanceof JTextComponent) {
                    JTextComponent jtc = (JTextComponent) c;
                    jtc.requestFocus();
                    jtc.selectAll();
                }
                return c;
            }
        }
    }
}

The Table Select All Editor should work for you. It is the preferred solution so you don't have to keep creating custom editors. That is the columns containing integers should only accept integers. With you current code

Your code does work partially. If you start editing using the F2 key, then the text is selected. However, when you use the mouse and double click on the cell then the second mouse event is passed to the editor so the caret can be positioned where you clicked and this removes the selection. A solution for this is:

final JTextComponent jtc = (JTextComponent)c;
jtc.requestFocus();
//jtc.selectAll();
SwingUtilities.invokeLater(new Runnable()
{
    public void run()
    {
        jtc.selectAll();
    }
});
public class SelectAllCellEditor extends DefaultCellEditor
{
    public SelectAllCellEditor(final JTextField textField ) {
        super( textField );
        textField.addFocusListener( new FocusAdapter()
        {
            public void focusGained( final FocusEvent e )
            {
                textField.selectAll();
            }
        } );
    }
}

JTables can have many different components in a cell. It is usually a JTextField when you are editing. You need to firstly get the field and then select. You can get the length of the text by working through your modal. This code should get you started, you may want to place it within a List selection handler. ie.

 ListSelectionModel rowSM = this.getSelectionModel();
 rowSM.addListSelectionListener(new ListSelectionListener() {
    public void valueChanged(ListSelectionEvent e){
       DefaultCellEditor ed = (DefaultCellEditor)this.getCellEditor();
       JTextField jf = (JTextField)ed.getComponent();
       jf.select(0, *text.length()*);
       jf.requestFocusInWindow();
    }
 });

Notably you will need to find the text.length(). Possibly something such as:

this.getModel().getValueAt(this.getSelectedRow(), this.getSelectedColumn()).length();

Disclaimer I haven't tested this code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM