I have One Jtable in which i have added JComobox like this.
TableColumn sportColumn = jTable1.getColumnModel().getColumn(2);
comboBox = new JComboBox();
comboBox.addItem("Snowboarding");
comboBox.addItem("Rowing");
comboBox.addItem("Chasing toddlers");
comboBox.addItem("Speed reading");
comboBox.addItem("Teaching high school");
comboBox.addItem("None");
sportColumn.setCellEditor(new DefaultCellEditor(comboBox));
and i have added one mouse event of jtable like this.
private void jTable1MouseClicked(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
try {
int row = jTable1.rowAtPoint(evt.getPoint());
int col = jTable1.columnAtPoint(evt.getPoint());
System.out.println("Row" + row + "Column" + col);
} catch (Exception e) {
e.printStackTrace();
}
}
and i am getting proper out put of row and column.
but when i click on the cell where i added Jcombobox that time its not giving out put of that row and column. still i have called clickevent of table in combobox click event but its giving all time row 0 and even column 0 here screen shot.
so how do i solved it so i can have that row and column?
As I see it, you have three basic options...
Attach a CellEditorListener
to the DefaultCellEditor
and monitor for editingStopped
events...
editor.addCellEditorListener(new CellEditorListener() {
@Override
public void editingStopped(ChangeEvent e) {
System.out.println("Editing stopped");
TableCellEditor editor = (TableCellEditor) e.getSource();
Object value = editor.getCellEditorValue();
System.out.println("Selected value = " + value);
}
@Override
public void editingCanceled(ChangeEvent e) {
}
});
The problem with this, is it's not possible to actually determine the cell that's been edited. Even with a reference to the JTable
, by the time you receive this event, the table is no longer in edit mode...So all you know is the value of the editor...
Attach a TableModelListener
to the TableModel
...
model.addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
int type = e.getType();
switch (type) {
case TableModelEvent.UPDATE:
if (e.getFirstRow() - e.getLastRow() == 0) {
TableModel model = (TableModel) e.getSource();
int row = e.getFirstRow();
int col = e.getColumn();
System.out.println("Update " + row + "x" + col + " = " + model.getValueAt(row, col));
}
break;
}
}
});
This will let you know when the value of a cell has changed (and a lot of other things, but this is what we're interested), what it won't tell you, is why it changed.
This approach is good, because it provides all the information you need to know in order to find the value and the cell.
Simply override the TableModel
's setValueAt
method and provide some sort of notification of your own...
While this is kind of duplicating the functionality of the TableModelListener
you could devise the event information so that it provides more relevant information as the TableModelEvent
covers a lot of user cases...
Example
Below is an example taken TableRenderDemo and modified to to demonstrate the first two concepts
import java.awt.BorderLayout;
import javax.swing.DefaultCellEditor;
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 java.awt.Component;
import java.awt.Dimension;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableModel;
/**
* TableRenderDemo is just like TableDemo, except that it explicitly initializes
* column sizes and it uses a combo box as an editor for the Sport column.
*/
public class TableRenderDemo extends JPanel {
public TableRenderDemo() {
super(new BorderLayout());
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));
//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();
model.addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
int type = e.getType();
switch (type) {
case TableModelEvent.UPDATE:
if (e.getFirstRow() - e.getLastRow() == 0) {
TableModel model = (TableModel) e.getSource();
int row = e.getFirstRow();
int col = e.getColumn();
System.out.println("Update " + row + "x" + col + " = " + model.getValueAt(row, col));
}
break;
}
}
});
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;
column.setPreferredWidth(Math.max(headerWidth, cellWidth));
}
}
public void setUpSportColumn(final JTable table,
TableColumn sportColumn) {
//Set up the editor for the sport cells.
JComboBox comboBox = new JComboBox();
comboBox.addItem("Snowboarding");
comboBox.addItem("Rowing");
comboBox.addItem("Knitting");
comboBox.addItem("Speed reading");
comboBox.addItem("Pool");
comboBox.addItem("None of the above");
TableCellEditor editor = new DefaultCellEditor(comboBox);
editor.addCellEditorListener(new CellEditorListener() {
@Override
public void editingStopped(ChangeEvent e) {
System.out.println("Editing stopped");
TableCellEditor editor = (TableCellEditor) e.getSource();
Object value = editor.getCellEditorValue();
System.out.println("Selected value = " + value);
}
@Override
public void editingCanceled(ChangeEvent e) {
}
});
sportColumn.setCellEditor(editor);
//Set up tool tips for the sport cells.
DefaultTableCellRenderer renderer
= new DefaultTableCellRenderer();
renderer.setToolTipText("Click for combo box");
sportColumn.setCellRenderer(renderer);
}
class MyTableModel extends AbstractTableModel {
private String[] columnNames = {"First Name",
"Last Name",
"Sport",
"# of Years",
"Vegetarian"};
private 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)}
};
public final Object[] longValues = {"Jane", "Kathy",
"None of the above",
new Integer(20), Boolean.TRUE};
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public int getRowCount() {
return data.length;
}
@Override
public String getColumnName(int col) {
return columnNames[col];
}
@Override
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.
*/
@Override
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
/*
* Don't need to implement this method unless your table's
* editable.
*/
@Override
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.
*/
@Override
public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
}
/**
* 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();
}
});
}
}