This is my first time asking here so forgive me if something isn't appropriate, and sorry if my English isn't very good.
Well, to make it short, currently I'm developing a Java desktop app with Swing and I have a problem using table. I have rows with each row have a button to delete the row. Everything is okay (i can delete rows with no problem) until i try to delete the last row. The last row can be deleted but apparently there is an exception, something like this:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 4 >= 4
at java.util.Vector.elementAt(Vector.java:427)
at javax.swing.table.DefaultTableModel.setValueAt(DefaultTableModel.java:648)
at javax.swing.JTable.setValueAt(JTable.java:2710)
at javax.swing.JTable.editingStopped(JTable.java:4712)
at javax.swing.AbstractCellEditor.fireEditingStopped(AbstractCellEditor.java:125)
From the stack trace, it seems that "4" is my previously deleted last row index, but i have no idea how to deal with this. I already search for solution but i still can't solve it. Note that there are still other rows when i delete the last row, and after that i can't delete the others rows. The same exception also resulted when i click the delete button.
Oh. and I use removeRow() from DefaultTableModel to delete the row. Any help will be appreciated. Thanks.
EDIT
These are the code I use.
public class ViewDetail extends JInternalFrame implements ActionListener {
...
String column[] = { "Aaa", "Bbb", "Delete This"};
tableModel = new DefaultTableModel();
Object row[][] = new Object[size][column.length];
//fill the data from db
int r = 0;
for (int i = 0; i < size; i++) {
row[r][0] = ...;
row[r][1] = ...;
row[r][2] = "Delete";
r++;
}
tableModel.setDataVector(row, column);
table = new JTable(tableModel);
tableColumn = table.getColumn("Aaa");
tableColumn.setPreferredWidth(75);
tableColumn = table.getColumn("Bbb");
tableColumn.setPreferredWidth(75);
tableColumn = table.getColumn("Delete This");
tableColumn.setPreferredWidth(75);
tableColumn.setCellRenderer(new ButtonRenderer());
tableColumn.setCellEditor(new ButtonEditor(new JCheckBox());
...
}
public class ButtonRenderer extends JButton implements TableCellRenderer {
public ButtonRenderer() {
setOpaque(true);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(UIManager.getColor("Button.background"));
}
setText((value == null) ? "" : value.toString());
return this;
}
}
public class ButtonEditor extends DefaultCellEditor {
protected JButton button;
private String label;
private boolean isPushed;
private JTable table;
public ButtonEditor(JCheckBox checkBox) {
super(checkBox);
button = new JButton();
button.setOpaque(true);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
fireEditingStopped();
}
});
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
if (isSelected) {
button.setForeground(table.getSelectionForeground());
button.setBackground(table.getSelectionBackground());
} else {
button.setForeground(table.getForeground());
button.setBackground(table.getBackground());
}
label = (value == null) ? "" : value.toString();
button.setText(label);
isPushed = true;
this.table = table;
return button;
}
public Object getCellEditorValue() {
if (isPushed) {
DefaultTableModel tableModel = (DefaultTableModel) table.getModel();
tableModel.removeRow(table.getSelectedRow());
}
isPushed = false;
return new String(label);
}
public boolean stopCellEditing() {
isPushed = false;
return super.stopCellEditing();
}
protected void fireEditingStopped() {
super.fireEditingStopped();
}
}
Swing is trying to set the new value into the row you remove! Try moving the remove code into a Runnable and use invokeLater in the swing utility class to execute it.
could you post the code where you init, add elements and delete in your JTable?
My first guess is that you are either doing the classical mistake
"I have 4 elements in my table so to delete the last one I remove(4)" when you your table goes from 0 to 3 in indices
or you are trying to remove several object in the same loop like
for(int i = 0; i<lenght; i++){
if(i%2==0){//every even number
tab.remove(i);
}
}
then your are modifying the size of your table, the elements are shifted but your not taking it in account when removing.
those are just guesses/pointer to what might cause the problem. please post your code if this doesn't solve it
The Table Button Column shows how you can render a column as a button and how to add an Action that is executed when the button is clicked. The example Action just happens to show how to delete a row.
Here you need to remove only 0 th row that should be iterated
private void refreshTable() {
int rowCount= model.getRowCount();
// System.out.println(rowCount);
for(int i=0;i<rowCount;i++ ){
model.removeRow(0);
//System.out.println(i);
}
}
you can add new vaiable and check to fireEditingStopped() :
public class ButtonEditor extends DefaultCellEditor {
//create new variable
private boolean isDeleteRow = false;
/////////////////
protected JButton button;
private String label;
private boolean isPushed;
private JTable table;
public ButtonEditor(JCheckBox checkBox) {
super(checkBox);
button = new JButton();
button.setOpaque(true);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
fireEditingStopped();
}
});
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
if (isSelected) {
button.setForeground(table.getSelectionForeground());
button.setBackground(table.getSelectionBackground());
} else {
button.setForeground(table.getForeground());
button.setBackground(table.getBackground());
}
label = (value == null) ? "" : value.toString();
button.setText(label);
isPushed = true;
this.table = table;
// set false when click to button
isDeleteRow = false;
/////////////////
return button;
}
public Object getCellEditorValue() {
if (isPushed) {
// set true when isPushed button
isDeleteRow = true;
/////////////////
}
isPushed = false;
return new String(label);
}
public boolean stopCellEditing() {
isPushed = false;
return super.stopCellEditing();
}
protected void fireEditingStopped() {
super.fireEditingStopped();
//check if isDeleteRow, remove row
if(isDeleteRow)
{
DefaultTableModel tableModel = (DefaultTableModel) table.getModel();
tableModel.removeRow(table.getSelectedRow());
}
/////////////////
}
}
Related
I would like to know how to set up a JComboBox in a particular cell in a JTable.
I have seen people using TableColumn setCellEditor(new DefaultCellEditor(comboBox)).
But this is for an entire column, I would like a specific cell.
So maybe I should do a custom TableCellEditor that would fit my needs, but I am a little lost on how to do it...
The goal of this is to manage filters on parameters. There are two kinds of filters:
The one that compares two values, for instance: number of balloons > 5
The one that will say is a value is inside a range of value, for instance: parameter name is inside {"one", "two", "three", "seven"}.
screenshot of my JTable:
As we can see in the picture, when there is the "comparator" "is among", we would need a JComboBox in cell[0][2] to choose the values of the range within a complete set of fields.
While cell[1][2] does not need a JComboBox, but just an editable cell.
I hope I have been clear and thank you for your help.
EDIT:
I was able to display a JComboBox only to realize, I couldn't select multiple values on it. So now I am trying to display a JList instead of a ComboBox.
But when I click on the cell, the JList is not displayed, I don't know why.
Here is my code:
JTable tableParametersFilter = new JTable(modelParametersFilter){
// Determine editor to be used by row
public TableCellEditor getCellEditor(int row, int column)
{
int modelColumn = convertColumnIndexToModel( column );
int modelRow = convertRowIndexToModel( row );
Parameter_Filter pf = view.listParameter_Filter.get(modelRow);
if(modelColumn == 2 && pf instanceof Parameter_Filter_To_List_Of_Fields) {
Parameter_Filter_To_List_Of_Fields pftlof = (Parameter_Filter_To_List_Of_Fields)pf;
JList<String> list = new JList<String>(pftlof.list_of_fields_total_names);
list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION );
list.setLayoutOrientation(JList.VERTICAL_WRAP);
list.setVisibleRowCount(-1);
return new TableCellEditor() {
#Override
public boolean stopCellEditing() {
return false;
}
#Override
public boolean shouldSelectCell(EventObject anEvent) {
return false;
}
#Override
public void removeCellEditorListener(CellEditorListener l) {
}
#Override
public boolean isCellEditable(EventObject anEvent) {
return true;
}
#Override
public Object getCellEditorValue() {
return list.getSelectedValuesList().toString();
}
#Override
public void cancelCellEditing() {
}
#Override
public void addCellEditorListener(CellEditorListener l) {
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
return list;
}
};
}
return super.getCellEditor(row, column);
}
};
Any suggestions?
I have solved my problem.
I have not been able to add multiple choice JComboBox, or a displayable JList on the Cell of the Jtable.
Instead, I have used a JOptionPane that displayed a JList.
Here's the code:
tableParametersFilter.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
JTable target = (JTable)e.getSource();
int row = target.getSelectedRow();
int column = target.getSelectedColumn();
if(column == 2){
Parameter_Filter pf = view.listParameter_Filter.get(row);
if(pf instanceof Parameter_Filter_To_List_Of_Fields) {
Parameter_Filter_To_List_Of_Fields pftlof = (Parameter_Filter_To_List_Of_Fields) pf;
JList<String> jlist = new JList<String>(pftlof.list_of_fields_total_names);
String StringOfIntArray = (String) tableParametersFilter.getValueAt( row, 2);
int[] list_parameter_id = Statique.StringOfIntArrayToIntegerArray(StringOfIntArray);
if(list_parameter_id.length < jlist.getModel().getSize()) {
int[] list_places = pftlof.getPlaceOfParameters(list_parameter_id);
for(int i = 0; i < list_places.length; i++) {
jlist.setSelectedIndices(list_places);
}
}
JScrollPane scrollPane = new JScrollPane(jlist);
scrollPane.setPreferredSize( new Dimension( 500, 500 ) );
JOptionPane.showMessageDialog(
null, scrollPane, "Multi-Select Example", JOptionPane.PLAIN_MESSAGE);
int[] SelectedIndices = jlist.getSelectedIndices();
Integer[] listParametersId = new Integer[SelectedIndices.length];
for(int i = 0; i < SelectedIndices.length; i++) {
int id = pftlof.list_of_fields_Total[SelectedIndices[i]].id;
try {
Parameter p = Parameter.getParameter(
id,
Parameter_Filter_To_List_Of_Fields.getTotal_Parameter_In_Parameter_Filter_To_List_Of_Fields());
listParametersId[i] = p.id;
} catch (NoSuchFieldException e1) {
e1.printStackTrace();
}
}
System.out.println(Arrays.toString(listParametersId));
tableParametersFilter.setValueAt(Arrays.toString(listParametersId), row, 2);
}
}
}
}
I am looking to modify the way cell input is handled in my JTable. Currently I am using a DefaultTableModel as seen below.
DefaultTableModel model = new DefaultTableModel() {
#Override
public boolean isCellEditable(int row, int col) {
return col == 1 || col == 2 || col == 6;
}
#Override
public Class getColumnClass(int col) {
if (col == 6) {
return Integer.class;
} else {
return String.class;
}
}
};
With this code column 6 forces the user to input an Integer. I would like to take this further by not allowing the number to be outside of a range (e.g. 1-100) and also for the field to never be empty (The column will have data in it prior to user interaction). I have read the docummentation but cannot seem to find anything that manages the behaviour of column types. Thanks!
You would need to create a custom editor.
The following example demonstrates and editor that forces the data to be 5 characters:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
public class TableFiveCharacterEditor extends DefaultCellEditor
{
private long lastTime = System.currentTimeMillis();
public TableFiveCharacterEditor()
{
super( new JTextField() );
}
public boolean stopCellEditing()
{
JTable table = (JTable)getComponent().getParent();
try
{
String editingValue = (String)getCellEditorValue();
if(editingValue.length() != 5)
{
JTextField textField = (JTextField)getComponent();
textField.setBorder(new LineBorder(Color.red));
textField.selectAll();
textField.requestFocusInWindow();
JOptionPane.showMessageDialog(
table,
"Please enter string with 5 letters.",
"Alert!",JOptionPane.ERROR_MESSAGE);
return false;
}
}
catch(ClassCastException exception)
{
return false;
}
return super.stopCellEditing();
}
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column)
{
Component c = super.getTableCellEditorComponent(
table, value, isSelected, row, column);
((JComponent)c).setBorder(new LineBorder(Color.black));
return c;
}
private static void createAndShowUI()
{
JTable table = new JTable(5, 5);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
// Use a custom editor
TableCellEditor fce = new TableFiveCharacterEditor();
table.setDefaultEditor(Object.class, fce);
JFrame frame = new JFrame("Table Five Character Editor");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( scrollPane );
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
You would need to modify the editor to make sure:
the data is an Integer by using the Integer.parseInt(...) method
that the Integer value is in your desired range
Edit:
how can I apply this to influence one column rather than the entire table.
You can add the editor to the TableColumn:
table.getColumnModel().getColumn(...).setCellEditor(...);
Overriding the behaviour of the DefaultCellEditor achieves the desired outcome.
DefaultCellEditor editor = new DefaultCellEditor(new JTextField()) {
#Override
public boolean stopCellEditing() {
JTable table = (JTable) getComponent().getParent();
try {
String value = (String) getCellEditorValue();
if (Integer.parseInt(value) < 1) {
JTextField textField = (JTextField) getComponent();
textField.setBorder(new LineBorder(Color.red));
textField.selectAll();
textField.requestFocusInWindow();
return false;
}
} catch (NumberFormatException ex) {
return false;
}
return super.stopCellEditing();
}
};
Then added to the desired column of the table.
table.getColumnModel().getColumn(6).setCellEditor(editor);
Edit: The behaviour inside the if statement will not occur if a NumberFormatException is thrown, you may want to put the same lines of code within the catch.
I am working on netbeans and creating a swing application. I have created a JComboBox and a JTable. I am able to add value from JComboBox to JTable on a button click but if I repeat the same process the same value is again again added to the table. How to stop adding the existed value of JComboBox.
This is the code of JComboBox
private void populateCombo(){
organizationComboBox.removeAllItems();
for (Organization.Type type : Organization.Type.values()){
organizationComboBox.addItem(type);
}
}
This is the code of JTable
private void populateTable(){
DefaultTableModel model = (DefaultTableModel) organizationTable.getModel();
model.setRowCount(0);
for (Organization organization : organizationDirectory.getOrganizationList()){
Object[] row = new Object[2];
row[0] = organization.getOrganizationID();
row[1] = organization.getName();
model.addRow(row);
}
}
This is the code for my add button
Type type = (Type) organizationComboBox.getSelectedItem();
Organization o = organizationDirectory.createOrganization(type);
if(type.equals(Type.Receptionist)){
o.getSupportedRole().add(new ReceptionistRole());
}else
if(type.equals(Type.Doctor)){
o.getSupportedRole().add(new DoctorRole());
}else
if(type.equals(Type.VaccineManager)){
o.getSupportedRole().add(new VaccineManagerRole());
}else
if(type.equals(Type.LabAssistant)){
o.getSupportedRole().add(new LabAssistantRole());
}else
if(type.equals(Type.Donor)){
o.getSupportedRole().add(new DonorRole());
}else
if(type.equals(Type.Patient)){
o.getSupportedRole().add(new PatientRole());
}
populateTable();
Thanks in advance.
Don't use DefaultTableModel. This class is only for simple cases and demo applications. Simply look here for example of your own model.
So your model will looks like:
public class OrganizationModel extends AbstractTableModel {
protected String[] columnNames;
protected List<Organization> dataVector;
public OrganizationModel(String[] columnNames) {
this.columnNames = columnNames;
dataVector = new ArrayList<Organization>();
}
public String getColumnName(int column) {
return columnNames[column];
}
public boolean isCellEditable(int row, int column) {
return false;
}
public Class getColumnClass(int column) {
return String.class;
}
public Object getValueAt(int row, int column) {
return column == 0? dataVector.get(row).getOrganizationID() : dataVector.get(row).getName();
}
public void addRowWhenNotExist(Organization o) {
if (!dataVector.contains(o)) {
dataVector.add(o);
fireTableRowsInserted(dataVector.size() - 1, dataVector.size() - 1);
}
}
}
For correct working of this example you also need correct definition of methods equals and hashCode for your class Organization.
public class Organization {
// your stuff
public boolean equals(Object another) {
if (another instanceof Organization) {
return getOrganizationID() == ((Organization) another).getOrganizationID();
} else {
return false;
}
}
public int hashCode() {
return getOrganizationID();
}
}
I have a JTable displaying rows from an SQL database. The table is relatively small (only 4 columns and up to 1000 rows).
I would like to give the user the opportunity to edit any cells in the table but want to avoid restricting it so much so that they must use an edit dialog box (this makes for far easier error checking and validation but is less intuitive)
I have tried a few different ways of controlling edit selections using the valueChanged method of my JTable but haven't had much luck.
I would like each row to be edited and written to the database at the conclusion of editing. I would like that once a cell has been clicked to start the editing of that row, no other rows can be selected until the user has finished editing the row (other rows are grayed out). After editing each cell and pressing enter, the edit selection should jump to the next column in the same row.
Can anyone give pointers on how I can achieve this?
// Create table with database data
table = new JTable(new DefaultTableModel(data, columnNames)) {
public Class getColumnClass(int column) {
for (int row = 0; row < getRowCount(); row++) {
Object o = getValueAt(row, column);
if (o != null){
return o.getClass();
}
}
return Object.class;
}
#Override
public boolean isCellEditable(int row, int col){
return true;
}
#Override
public boolean editCellAt(int row, int column) {
boolean ans = super.editCellAt(row, column);
if (ans) {
Component editor = table.getEditorComponent();
editor.requestFocusInWindow();
}
return ans;
}
#Override
public void valueChanged(ListSelectionEvent source) {
super.valueChanged(source);
if (table!=null)
table.changeSelection(getSelectedRow(), getSelectedColumn()+1, false, false);
}
};
Edit - custom cell editor with table pointer seems to be a start
public class ExchangeTableCellEditor extends AbstractCellEditor implements TableCellEditor {
private JTable table;
JComponent component = new JTextField();
public ExchangeTableCellEditor(JTable table) {
this.table = table;
}
public boolean stopCellEditing() {
boolean ans = super.stopCellEditing();
//now we want to increment the cell count
table.editCellAt(table.getSelectedRow(), table.getSelectedColumn()+1);
return ans;
}
#Override
public void cancelCellEditing() {
//do nothing... must accept cell changes
}
#Override
public Object getCellEditorValue() {
return ((JTextField)component).getText();
}
#Override
public Component getTableCellEditorComponent(JTable arg0, Object value,
boolean arg2, int arg3, int arg4) {
((JTextField)component).setText((String)value);
return component;
}
}
The default renderer and editor is typically adequate for most data types, but you can define custom renderers and editors as needed.
Addendum: I'm unfamiliar with the approach shown in your fragment. Instead, register a TableModelListener with your model, as shown below, and update the database with whatever granularity is warranted. See also How to Use Tables: Listening for Data Changes.
Addendum: #kleopatra is correct about your TableCellEditor. One convenient way to notify listeners is to invoke the super implementation, as shown here. Note that the delegate invokes fireEditingStopped().
/** #see https://stackoverflow.com/questions/9155596 */
public class NewJavaGUI extends JPanel {
private final JTable table;
public NewJavaGUI() {
String[] colNames = {"C1", "C2", "C3"};
DefaultTableModel model = new DefaultTableModel(colNames, 0) {
#Override
public boolean isCellEditable(int row, int col) {
// return your actual criteria
return true;
}
#Override
public Class getColumnClass(int col) {
// return your actual type tokens
return getValueAt(0, col).getClass();
}
};
// Add data; note auto-boxing
model.addRow(new Object[]{"A1", "A2", 42});
model.addRow(new Object[]{"B1", "B2", 42d});
model.addTableModelListener(new TableModelListener() {
#Override
public void tableChanged(TableModelEvent e) {
// DML as indicated
}
});
table = new JTable(model);
this.add(table);
}
private void display() {
JFrame f = new JFrame("NewJavaGUI");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new NewJavaGUI().display();
}
});
}
}
The behaviour you mention can be achieved by forcing your table to start editing again.
First make sure you now yourRow and Column and that you add your own tablecelleditor that extands from the AbstractCellEditor
then add this to your stopCellEditing method:
EventQueue.invokeLater(new Runnable()
{
public void run()
{
yourTable.editCellAt( yourRow, yourColumn+1);
}
});
The default behavior of a JTable is to append to the contents when you start typing, and to place the caret at the clicked location when clicking. I want the behavior of both these things to change, so the contents is replaced when I edit a cell, either by typing or by clicking and then typing. When I click a cell and then change the caret position, however, I want the contents to stay so I can change it.
I know how to select all when the cell becomes editing, by replacing the cell editor with one that selects all inside a SwingUtilities.invokeLater (see elsewhere), but that causes the typing behavior to break. When I do this and start typing in a cell, first the typed character is appended to the string, then it is selected (but the selection is invisible!) and when typing another character the contents gets replaced by that.
Is there a way to replace the contents immediately when typing in a highlighted (but not editing) cell, but select all when clicking a cell?
Here is the code I use for the CellEditor:
public class TextFieldCellEditor extends JTextField implements TableCellEditor
{
private CellEditorListener cellEditorListener = null;
private boolean isInteger = false;
private Object oldValue;
// Start editing
#Override
public Component getTableCellEditorComponent(JTable table, Object obj, boolean isSelected, int row, int column)
{
Color color2 = DefaultLookup.getColor(this, ui, "Table.alternateRowColor");
super.setBackground(color2 != null && (row & 1) == 1? color2 : table.getBackground());
super.setForeground(table.getForeground());
super.setBorder(DefaultLookup.getBorder(this, ui, "Table.focusCellHighlightBorder"));
super.setText(obj.toString());
isInteger = obj instanceof Integer;
if (isInteger)
{
super.setHorizontalAlignment(SwingConstants.RIGHT);
oldValue = obj;
}
// SwingUtilities.invokeLater(new Runnable()
// {
// public void run()
// {
// TextFieldCellEditor.this.selectAll();
// }
// });
return this;
}
// Retrieve e dited value
#Override
public Object getCellEditorValue()
{
if (isInteger)
{
// Try to convert to integer. If input is invalid, revert.
try
{
return new Integer(super.getText());
}
catch (NumberFormatException e)
{
return oldValue;
}
}
return super.getText();
}
#Override
public boolean isCellEditable(EventObject e)
{
return true;
}
#Override
public boolean shouldSelectCell(EventObject e)
{
return true;
}
#Override
public boolean stopCellEditing()
{
cellEditorListener.editingStopped(new ChangeEvent(this));
return true;
}
#Override
public void cancelCellEditing()
{
cellEditorListener.editingCanceled(new ChangeEvent(this));
}
#Override
public void addCellEditorListener(CellEditorListener celleditorlistener)
{
cellEditorListener = celleditorlistener;
}
#Override
public void removeCellEditorListener(CellEditorListener celleditorlistener)
{
if (cellEditorListener == cellEditorListener) cellEditorListener = null;
}
}
In your getTableCellEditorComponent() implementation, add the following:
if (isSelected) {
this.selectAll();
}
As an aside, why not extend AbstractCellEditor or DefaultCellEditor(JTextField textField)? See also How to Use Tables: Using Other Editors.
Addendum: See also Table Select All Renderer and Table Select All Editor.
The cleanest solution I could find for this case was to overwrite the JTable's editCellAt and inform the CellEditor of how the edit was triggered:
#Override
public boolean editCellAt(int row, int column, EventObject e) {
cellEditor.setKeyTriggered(e instanceof KeyEvent);
return super.editCellAt(row, column, e);
}
And here is the relevant CellEditor code:
public class MyCellEditor extends DefaultCellEditor {
private boolean keyTriggered;
public MyCellEditor() {
super(new JTextField());
final JTextField textField = (JTextField) getComponent();
textField.addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent e) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
if (!keyTriggered) {
textField.selectAll();
}
}
});
}
});
}
public void setKeyTriggered(boolean keyTriggered) {
this.keyTriggered = keyTriggered;
}
#Override
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column) {
final JTextField textField = (JTextField)
super.getTableCellEditorComponent(table, value, isSelected, row, column);
textField.selectAll();
return textField;
}
}