now I double click to select the item "football" and press del and then enter, I now got an empty cell
now I click the cell again and type "f", I am expecting it display the autocomplete for "Football", but it only display the char and cell lost it's focus immediately
- Code: Select all
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import com.jidesoft.swing.AutoCompletion;
import com.jidesoft.swing.ComboBoxSearchable;
:shock: public class TableRenderDemo extends JPanel
{
private boolean DEBUG = false;
private ComboEditor editor = new ComboEditor();
public TableRenderDemo()
{
super(new GridLayout(1, 0));
JTable table = new JTable(new MyTableModel());
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
table.setFillsViewportHeight(true);
// Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
// Set up column sizes.
initColumnSizes(table);
// Fiddle with the Sport column's cell editors/renderers.
setUpSportColumn(table, table.getColumnModel().getColumn(2));
table.getColumnModel().getColumn(4).setCellEditor(new CheckboxEditor(editor));
// Add the scroll pane to this panel.
add(scrollPane);
}
/*
* This method picks good column sizes. If all column heads are wider than
* the column's cells' contents, then you can just use
* column.sizeWidthToFit().
*/
private void initColumnSizes(JTable table)
{
MyTableModel model = (MyTableModel) table.getModel();
TableColumn column = null;
Component comp = null;
int headerWidth = 0;
int cellWidth = 0;
Object[] longValues = model.longValues;
TableCellRenderer headerRenderer = table.getTableHeader().getDefaultRenderer();
for (int i = 0; i < 5; i++)
{
column = table.getColumnModel().getColumn(i);
comp = headerRenderer.getTableCellRendererComponent(null, column.getHeaderValue(), false, false, 0, 0);
headerWidth = comp.getPreferredSize().width;
comp = table.getDefaultRenderer(model.getColumnClass(i)).getTableCellRendererComponent(table,
longValues[i], false, false, 0, i);
cellWidth = comp.getPreferredSize().width;
if (DEBUG)
{
System.out
.println("Initializing width of column " + i + ". " + "headerWidth = " + headerWidth + "; cellWidth = " + cellWidth);
}
column.setPreferredWidth(Math.max(headerWidth, cellWidth));
}
}
public void setUpSportColumn(JTable table, TableColumn sportColumn)
{
// Set up the editor for the sport cells.
sportColumn.setCellEditor(editor);
// Set up tool tips for the sport cells.
DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
renderer.setToolTipText("Click for combo box");
sportColumn.setCellRenderer(renderer);
}
/**
* Custom editor that changes the combo choices based on the "Vegetarian"
* column value
*/
class ComboEditor extends DefaultCellEditor
{
DefaultComboBoxModel model;
Map<String, List<String>> choicesMap;
public ComboEditor()
{
super(new JComboBox());
JComboBox combo = (JComboBox) getComponent();
AutoCompletion complete = new AutoCompletion(combo, new ComboBoxSearchable(combo));
complete.setStrict(true);
model = (DefaultComboBoxModel) combo.getModel();
((JComboBox) getComponent()).setEditable(true);
((JComboBox) getComponent()).addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
}
});
buildComboMap();
}
private void buildComboMap()
{
choicesMap = new HashMap<String, List<String>>();
// for "true"
List<String> choices = new ArrayList<String>();
choices.add("Knitting");
choices.add("Interior Decoration");
choicesMap.put("true", choices);
// for "false"
choices = new ArrayList<String>();
choices.add("Football");
choices.add("Hockey");
choices.add("Kickboxing");
choicesMap.put("false", choices);
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
{
model.removeAllElements();
String keyColumnValue = table.getValueAt(row, table.getColumnModel().getColumnIndex("Vegetarian"))
.toString();
for (String item : choicesMap.get(keyColumnValue))
{
model.addElement(item);
// ((AbstractTableModel)
// table.getModel()).fireTableCellUpdated(row, 2);
// ((AbstractTableModel)
// table.getModel()).fireTableDataChanged();
}
return super.getTableCellEditorComponent(table, value, isSelected, row, column);
}
@Override
public boolean stopCellEditing()
{
System.out.println(this.getCellEditorValue());
return super.stopCellEditing();
}
public boolean shouldSelectCell(EventObject anEvent)
{
return delegate.shouldSelectCell(anEvent);
}
}
class CheckboxEditor extends DefaultCellEditor
{
DefaultComboBoxModel model;
Map<String, List<String>> choicesMap;
ComboEditor editor;
public CheckboxEditor(ComboEditor editor)
{
super(new JCheckBox());
//
this.editor = editor;
buildComboMap();
}
private void buildComboMap()
{
choicesMap = new HashMap<String, List<String>>();
// for "true"
List<String> choices = new ArrayList<String>();
choices.add("Knitting");
choices.add("Interior Decoration");
choicesMap.put("true", choices);
// for "false"
choices = new ArrayList<String>();
choices.add("Football");
choices.add("Hockey");
choices.add("Kickboxing");
choicesMap.put("false", choices);
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
{
Boolean flag = (Boolean) value;
System.out.println(value);
JComboBox sportsCombo = (JComboBox) editor.getTableCellEditorComponent(table, value, isSelected, row, 2);
model = (DefaultComboBoxModel) (sportsCombo).getModel();
model.removeAllElements();
for (String item : choicesMap.get(flag.toString()))
{
model.addElement(item);
sportsCombo.setSelectedIndex(0);
}
((AbstractTableModel) table.getModel()).setValueAt(model.getElementAt(0), row, 2);
((AbstractTableModel) table.getModel()).fireTableCellUpdated(row, 2);
((AbstractTableModel) table.getModel()).fireTableDataChanged();
return super.getTableCellEditorComponent(table, value, isSelected, row, column);
}
}
class MyTableModel extends AbstractTableModel
{
private String[] columnNames =
{ "First Name", "Last Name", "Sport", "# of Years", "Vegetarian" };
private Object[][] data =
{
{ "Mary", "Campione", "Football", new Integer(5), new Boolean(false) },
{ "Alison", "Huml", "Interior Decoration", new Integer(3), new Boolean(true) },
{ "Kathy", "Walrath", "Hockey", new Integer(2), new Boolean(false) },
{ "Sharon", "Zakhour", "Knitting", new Integer(20), new Boolean(true) },
{ "Philip", "Milne", "Kickboxing", new Integer(10), new Boolean(false) } };
public final Object[] longValues =
{ "Sharon", "Campione", "None of the above", new Integer(20), Boolean.TRUE };
public int getColumnCount()
{
return columnNames.length;
}
public int getRowCount()
{
return data.length;
}
public String getColumnName(int col)
{
return columnNames[col];
}
public Object getValueAt(int row, int col)
{
return data[row][col];
}
/*
* JTable uses this method to determine the default renderer/ editor for
* each cell. If we didn't implement this method, then the last column
* would contain text ("true"/"false"), rather than a check box.
*/
public Class getColumnClass(int c)
{
return getValueAt(0, c).getClass();
}
/*
* Don't need to implement this method unless your table's editable.
*/
public boolean isCellEditable(int row, int col)
{
// Note that the data/cell address is constant,
// no matter where the cell appears onscreen.
if (col < 2)
{
return false;
}
else
{
return true;
}
}
/*
* Don't need to implement this method unless your table's data can
* change.
*/
public void setValueAt(Object value, int row, int col)
{
if (DEBUG)
{
System.out.println("Setting value at " + row + "," + col + " to " + value + " (an instance of " + value
.getClass() + ")");
}
data[row][col] = value;
fireTableCellUpdated(row, col);
if (DEBUG)
{
System.out.println("New value of data:");
printDebugData();
}
}
private void printDebugData()
{
int numRows = getRowCount();
int numCols = getColumnCount();
for (int i = 0; i < numRows; i++)
{
System.out.print(" row " + i + ":");
for (int j = 0; j < numCols; j++)
{
System.out.print(" " + data[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("TableRenderDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create and set up the content pane.
TableRenderDemo newContentPane = new TableRenderDemo();
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();
}
});
}
}