To put this short:
What is this about
I have a JTable with Model which displays data fetched from an SAP system.
My Goal is in a specific column to display only a part of the data which is in the model. For example the row of the model has Object["a","b"] but the user is only supposed to see a.
So I read a lot of threads here on StackOverflow and a lot of tutorials on how to use custom tablecellrenderers and editors etc. but I am not able to fix my problem, which is that the cell where i registered the renderer will not be highlighted when selected.
A possible solution is described HERE but this does not work for me.
Here is my custom Renderer:
public class SapChangeNumberCellRenderer extends DefaultTableCellRenderer{
private static final long serialVersionUID = -2649719064483586819L;
private SapChangeNumberTable table;
private int valuesSize;
public final static String ASM_AMOUNT = LanguageServer.getString("71", "Baugruppen");
public SapChangeNumberCellRenderer(SapChangeNumberTable table) {
super();
this.table = table;
}
#Override
public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected,
final boolean hasFocus,
final int row, final int column) {
// components & Layout
JPanel panel = new JPanel(new BorderLayout());
JButton buttonDots = new JButton("...");
JLabel text = new JLabel();
List<String> values = (List<String>) value;
valuesSize = values.size();
if (valuesSize > 0) {
// set values
buttonDots.setPreferredSize(new Dimension(14, 14));
text.setText(values.get(0));
} else {
text.setText("");
}
if (valuesSize > 1) {
// button to open dialog only if we have more than 1 item
panel.add(buttonDots, BorderLayout.EAST);
}
panel.add(text, BorderLayout.WEST);
panel.setOpaque(true);
return panel;
}
#Override
public String getToolTipText(MouseEvent e) {
String toolTip = String.valueOf(valuesSize) + Initializer.SPACE + ASM_AMOUNT;
return toolTip;
}
public SapChangeNumberTable getTable() {
return table;
}
}
So as you can see depending on the list size of the values I manipulate the component which will be given back from the method. The setOpaque(true) method does somehow not achieve my goal.
Here is the according JTabel (note: BaseTable is just a wrapper for JTable with some goodies I need...nothing fancy here)
public class SapChangeNumberTable extends BaseTable {
/** the model */
private SapChangeNumberTableModel model = new SapChangeNumberTableModel();
/** parent frame */
private SapPanel parent = null;
public SapChangeNumberTable(SapPanel parent) {
this.parent = parent;
this.init();
}
/**
* init the table
*/
private void init() {
// set model (not filled yet)
this.setModel(model);
// set renderer
setRendererAndEditor();
// add search filter row, enabling sorting is included
this.addFilterSearchRowPanel();
// single selection
this.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
// hide
this.hideColumns();
this.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
}
/**
* sets the default table cell renderer
*/
private void setRendererAndEditor() {
getColumnModel().getColumn(convertColumnIndexToView(SapChangeNumberTableModel.COL_ID_SPM_ASM_NUMBER))
.setCellRenderer(new SapChangeNumberCellRenderer(this));
getColumnModel().getColumn(convertColumnIndexToView(SapChangeNumberTableModel.COL_ID_SPM_ASM_NUMBER))
.setCellEditor(new SapChangeNumberAsmRefTableCellEditor(this));
}
#Override
public void setStatusBarDataCount(boolean value) {
}
#Override
public void hideColumns() {
}
#Override
public int getColModelSortIndex() {
return 0;
}
#Override
public void load() {
}
#Override
public SapChangeNumberTableModel getModel() {
return model;
}
public boolean isChanging() {
return model.isFilling();
}
public SapFactoryChange getRow(int row) {
return model.getSapFactoryChange(row);
}
#Override
public void clear() {
model.clear();
}
#Override
public Component prepareRenderer(TableCellRenderer renderer, int rowIndex, int vColIndex) {
Component comp = super.prepareRenderer(renderer, rowIndex, vColIndex);
if (vColIndex == SapChangeNumberTableModel.COL_ID_SPM_ASM_NUMBER) {
//what the hack to do here to manipulate the comp ? I can't add a JPanel to a plain Component
}
return comp;
}
}
In the table I tried some stuff with prepareRenderer but here I can't manipulate the data (values) and all other stuff I am doing in the custom renderer. Maybe I have a basic understanding problem of how to approach this. I am thankful for any hints !
I just found a very simple solution which I thought would overwrite my wanted behavior, but it doesn't.
Just implemented this into the Table:
#Override
public Component prepareRenderer(TableCellRenderer renderer, int rowIndex, int vColIndex) {
Component comp = super.prepareRenderer(renderer, rowIndex, vColIndex);
if (isRowSelected(rowIndex)) {
comp.setBackground(Color.ORANGE);
}
return comp;
}
works like a charme!
Related
I am trying to add a button inside a table cell. I am using the drag and drop method of netbeans since I know nothing about coding and will appreciate if you can teach me to code it. Thanks!
If you are using drag&drop in netbean for swing,
I highly advise you to touch the fundamental of swings , get your hands dirty so that you will know what is going on and how does the code work.
let me run through how you can achieve this. it will consist of 3 classes so that you will have a better understanding on what is going on and it practices oop too but of cause you can modify it to your preferred design pattern.
_main.java
public class _main extends JFrame{
private static final long serialVersionUID = 1L;
// Create new JFrame
_main(){
new JFrame("Main");
setLayout(new BorderLayout());
setSize(500,300);
add(new JLabel("Table Example ", SwingUtilities.CENTER) , BorderLayout.PAGE_START);
// ---------------- Call the method you have created in tableView.java ------------
add(new JScrollPane(new tableView(this).sampleTable()), BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args){
//Run Program
new _main();
}
}
tableView.java
public class tableView {
JFrame frame = new JFrame();
public tableView(JFrame frame) {
this.frame = frame;
}
//Create columnTitle & Table Model
String[] columnTitle = { "Data 1", "Data 2", "Data 3", "Buttons " };
DefaultTableModel model = new DefaultTableModel(columnTitle, 0);
public JTable sampleTable(){
JTable _dataTable = new JTable(model) {
#Override
public void updateUI() {
super.updateUI();
setRowHeight(34);
setAutoCreateRowSorter(true);
//------------ Placing button at your desired column ------------
TableColumn column;
column = getColumnModel().getColumn(3);
column.setCellRenderer(new tableModel(frame).new viewRenderer());
column.setCellEditor(new tableModel(frame).new ButtonsEditorView(this));
}
};
DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
centerRenderer.setHorizontalAlignment(JLabel.CENTER);
//-------- Adding data to your table row , use for loop for multiple data ---------
model.addRow(new Object[]{"1","2","3"});
return _dataTable;
}
}
tableModel.java
public class tableModel extends tableView{
public tableModel(JFrame frame) {
super(frame);
}
class viewButton extends JPanel {
public JButton viewbtnp = new JButton("View");
protected viewButton() {
setOpaque(true);
setFocusable(false);
add(viewbtnp);
}
}
class viewRenderer implements TableCellRenderer {
private final viewButton panel = new viewButton() {
#Override
public void updateUI() {
super.updateUI();
setName("Table.cellRenderer");
}
};
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
panel.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
return panel;
}
}
class ViewAction extends AbstractAction {
private final JTable table;
protected ViewAction(JTable table) {
super("view");
this.table = table;
}
#Override
public void actionPerformed(ActionEvent e) {
//--------------------------- Create your own function on what you want the button to do when button is clicked -------------
System.out.println("Clicked ");
}
}
class ButtonsEditorView extends AbstractCellEditor implements TableCellEditor {
protected final viewButton panel = new viewButton();
protected final JTable table;
protected ButtonsEditorView(JTable table) {
super();
this.table = table;
panel.viewbtnp.setAction(new ViewAction(table));
}
#Override
public Component getTableCellEditorComponent(JTable tbl, Object value, boolean isSelected, int row,
int column) {
panel.setBackground(tbl.getSelectionBackground());
return panel;
}
#Override
public Object getCellEditorValue() {
return "";
}
}
}
Output
Hope it helps.
Cheers
I have taken a jtable, and added a model to it, and added text area rendere and editor to it.
Table.setModel(
JUTableBindingFactory.createAttributeListBinding(
Binding, Table name, View name, null, null, attributes));
Table.getColumnModel()
.getColumn(i)
.setCellEditor(
new TextAreaEditor(
true, true, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER));
Table.getColumnModel()
.getColumn(i)
.setCellRenderer(
new TextAreaCellRenderer(
true, true, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER));
_Table.setRowHeight(100);
Also I have set the table row hieght.
Text area renderer class
public class TextAreaCellRenderer extends JTextArea implements TableCellRenderer
{
private JScrollPane pane;
private boolean _isEditable = false;
private boolean _isEnabled = false;
private int _verticalBarProperyValue = JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED;
private int _horizontalBarProperyValue = JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED;
public TextAreaCellRenderer()
{
super();
init();
}
public TextAreaCellRenderer(boolean isEnabled, boolean isEditable, int
verticalBarProperyValue, int horizontalBarProperyValue)
{
super();
_isEditable = isEditable;
_isEnabled = isEnabled;
_verticalBarProperyValue = verticalBarProperyValue;
_horizontalBarProperyValue = horizontalBarProperyValue;
init();
}
private void init()
{
pane = new JScrollPane(this, _verticalBarProperyValue, _horizontalBarProperyValue);
setLineWrap(true);
setWrapStyleWord(true);
setEditable(_isEditable);
setEnabled(_isEnabled);
}
/**
* Returns the cell renderer component.
*/
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column)
{
setLineWrap(true);
setWrapStyleWord(true);
setText(value != null ? value.toString() : "");
setBackground((isSelected) ? NWSTheme.BLUE_DARK : NWSTheme.WHITE);
setForeground((isSelected) ? NWSTheme.WHITE : NWSTheme.BLACK);
pane.setEnabled(true);
return pane;
}
}
the editor class is also quite similar, but the problem doesn't seem to be relating to this, what else should i try?
Try moving the horizontal scroll more up as sometimes we don't and are given the impression of what you experienced. Try atleast
Does someone know a good way to display the sorting icons in the header of a JTable, without using the build in sort functionality?
The sorting is done by the table model (actually a database) and not by the JTable itself. Thats why the automatic display of the icons doesn't work. Maybe one can insert a dummy RowSorter that does nothing, but makes the sort icons appear?
I found a better Solution
I just wrote my own RowSorter, so that the sorting does not have any effect, but redirects the sorting request to the model instead. That way the sort order is displayed by the look and feel itself. Some Pseudocode:
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import javax.swing.RowSorter;
import xyz.SortableTableModel;
public class MyRowSorter<M extends SortableTableModel> extends RowSorter<M> {
private M tableModel;
private List<? extends SortKey> sortKeys = new LinkedList<>();
public MyRowSorter(M tableModel) {
this.tableModel = tableModel;
}
#Override
public M getModel() {
return tableModel;
}
#Override
public void toggleSortOrder(int column) {
// redirecting sort request to model and modification of sortKeys
List<? extends SortKey> newSortKeys = ...;
setSortKeys(newSortKeys);
}
#Override
public int convertRowIndexToModel(int index) {
return index; // will always be the same
}
#Override
public int convertRowIndexToView(int index) {
return index; // will always be the same
}
#Override
public void setSortKeys(List<? extends SortKey> keys) {
if (keys == null) {
sortKeys = Collections.EMPTY_LIST;
} else {
sortKeys = Collections.unmodifiableList(keys);
}
fireSortOrderChanged();
}
#Override
public List<? extends SortKey> getSortKeys() {
return sortKeys;
}
#Override
public int getViewRowCount() {
return tableModel.getRowCount();
}
#Override
public int getModelRowCount() {
return tableModel.getRowCount();
}
// no need for any implementation
#Override public void modelStructureChanged() { }
#Override public void allRowsChanged() { }
#Override public void rowsInserted(int firstRow, int endRow) { }
#Override public void rowsDeleted(int firstRow, int endRow) { }
#Override public void rowsUpdated(int firstRow, int endRow) { }
#Override public void rowsUpdated(int firstRow, int endRow, int column) { }
}
In that case you can try to write a custom TableCellRenderer for JTableHeader.
Here is simple example of renderer:
private static class MyRenderer implements TableCellRenderer {
private ImageIcon icon1;
private ImageIcon icon2;
private TableCellRenderer defaultRenderer;
MyRenderer(JTable t){
defaultRenderer = t.getTableHeader().getDefaultRenderer();
icon1 = new ImageIcon(getClass().getResource("1.png"));
icon2 = new ImageIcon(getClass().getResource("2.png"));
}
#Override
public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
Component c = defaultRenderer.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, col);
if(col%2 == 0){
((JLabel)c).setIcon(icon1);
} else {
((JLabel)c).setIcon(icon2);
}
return c;
}
}
Here icon1 and icon2 is your sorting icons.
And you can set that renderer for your JTableHeader like next:
table.getTableHeader().setDefaultRenderer(new MyRenderer(table));
table - is your JTable.
The sorting is done by the table model (actually a database) and not by the JTable itself.
Check out the DefaultRowSorter class. Maybe you use the setSortsOnUpdates(...) and setSortKeys(...) so the sorting icons match the sort from the database. You could try:
Creating an empty model
Set the sort keys
use setSortsOnUpdates(false);
Update the model using the setDataVector() (or some equivalent method if using a custom model)
Note this approach assumes you have created the TableModel with column names and no data and added the model to the JTable. I think you will then also need to use:
table.setAutoCreateColumnsFromModel(false);
to prevent the TableColumnModel from being recreated when you load the data into the model.
Solution is tricky when you want your code to work with other existing Swing layouts (I am talking about com.formdev .... flatlaf ). These L&Fs create a special Header renderer.
Here is a simple solution that will work with all main L&Fs on the market (tatoo, formdev, jgoodies). The trick is to subclass from DefaultTableCellHeaderRenderer but also to pass the table look and feel current header renderer as parameter.
// this custom renderer will display the sorting icon for all afftected columns.
class CustomTableHeaderRenderer extends DefaultTableCellHeaderRenderer implements TableCellRenderer{
final private Icon ascIcon = UIManager.getIcon("Table.ascendingSortIcon");
final private Icon descIcon = UIManager.getIcon("Table.descendingSortIcon");
TableCellRenderer iTableCellRenderer = null;
public CustomTableHeaderRenderer(TableCellRenderer tableCellRenderer)
{
iTableCellRenderer = tableCellRenderer;
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JLabel label = (JLabel) iTableCellRenderer.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column) ;
List<? extends SortKey> sortKeys = table.getRowSorter().getSortKeys();
label.setIcon(null);
for (SortKey sortKey : sortKeys) {
if (sortKey.getColumn() == table.convertColumnIndexToModel(column)){
SortOrder o = sortKey.getSortOrder();
label.setIcon(o == SortOrder.ASCENDING ? ascIcon : descIcon);
break;
}
}
return label;
}
}
yourTable.getTableHeader().setDefaultRenderer( new CustomTableHeaderRenderer( yourTable.getTableHeader().getDefaultRenderer() ));
I have celltable with 4 column (name size addedBy modifiedBy )
all the value is filled during the run time.
The table actully show the documents.
Documents can be pdf, txt , doc so
i want to add icon before the name of the document.
and i also want one more Image column before name column
My code so far.
*
private CellTable<FDocument> getDocumentTable() {
if (documentTable == null) {
documentTable = new CellTable<FDocument>();
documentTable.setSize("600px", "300px");
documentTable.addColumn(nameColumnD, "NAME");
documentTable.addColumn(sizeColumnD, "SIZE");
documentTable.addColumn(modified_by_ColumnD, "MODIFIED BY");
documentTable.addColumn(dateColumnD, "MODIFIED ON");
}
return documentTable;
}
TextColumn<FDocument> idColumnD = new TextColumn<FDocument>() {
#Override
public String getValue(FDocumentobject) {
// TODO Auto-generated method stub
return object.getId();
}
};
TextColumn<FDocument> nameColumnD = new TextColumn<FDocument>() {
#Override
public String getValue(FDocumentobject) {
return object.getName();
}
};
TextColumn<FDocument> sizeColumnD = new TextColumn<FDocument>() {
#Override
public String getValue(FDocumentobject) {
return object.getSize();
}
};
TextColumn<FDocument> modified_by_ColumnD = new TextColumn<FDocument>() {
#Override
public String getValue(FilenetDocument object) {
return object.getModifiedBy();
}
};
TextColumn<FDocument> dateColumnD = new TextColumn<FDocument>(){
#Override
public String getValue(FDocumentobject){
return object.getModifiedOn();
}
};
private void addValuesToTable(){
List<FDocument> FDC = null;
/*
* Adding data to folder Table
*/
ArrayList<FDocument> documentsArrayList = new ArrayList<FDocument>();
Iterator<String> iteratorDocument = documents.getDocuments().getDocumentCollection().keySet().iterator();
while(iteratorDocument.hasNext()){
String key = iteratorDocument.next().toString();
FDocument value = documents.getDocuments().getDocumentCollection().get(key);
documentsArrayList.add(new FDocument(value.getName(), value.getSize(),value.getModifiedBy(), value.getModifiedOn(),value.getId()));
}
FDC = documentsArrayList;
// Create a data provider.
ListDataProvider<FDocument> dataProvider1 = new ListDataProvider<FDocument>();
// Connect the table to the data provider.
dataProvider1.addDataDisplay(documentTable);
// Add the data to the data provider, which automatically pushes it to the widget.
List<FDocument> listDocument = dataProvider1.getList();
for (FDocument fDocument: FDC) {
listDocument.add(fDocument1);
}
This the way i have made my table and the value.
Plz any one tell me the procedure
to add icon before the name of the document.
and i also want one more Image column before name column
Use DefaultTableCellRenderer to set custom renderer against the column with the desired icon. As shown below, the renderer creates a new label to mask all the cells within the selected column.
private class CellRenderer extends DefaultTableCellRenderer
{
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
JLabel label = new JLabel((String)value);
label.setOpaque(true);
Icon icon = new ImageIcon("icon.png");
label.setIcon(icon);
return label;
}
}
And then apply it to your table as shown below:
table.getColumnModel().getColumn(0).setCellRenderer(new CellRenderer());
Edited:
If you're using GWT then see here for an example code for Grid Cell format.
For creating image column, You need to define a custom renderer that sets the icon on the label
import java.awt.Component;
import javax.swing.ImageIcon;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
public class MyRenderer extends DefaultTableCellRenderer {
/*
* #see TableCellRenderer#getTableCellRendererComponent(JTable, Object, boolean, boolean, int, int)
*/
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int column) {
ImageIcon icon = new ImageIcon(getClass().getResource("images/moon.gif"));
setText((String)value);
setIcon(icon);
return this;
}
}
And then, use the renderer in a table as follows,
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
public class Sample {
public static void main(String[] args) {
JFrame f = new JFrame("Sample");
f.getContentPane().setLayout(new GridLayout(1,0,0,0));
TableModel model = new AbstractTableModel() {
public Object getValueAt(int rowIndex, int columnIndex) {
return rowIndex + "," + columnIndex;
}
public int getColumnCount() {
return 3;
}
public int getRowCount() {
return 10;
}
};
JTable table = new JTable(model);
table.getColumnModel().getColumn(1).setCellRenderer(new MyRenderer());
JScrollPane pane = new JScrollPane(table);
f.getContentPane().add(pane);
f.pack();
f.setVisible(true);
}
}
Both of these will probably need a custom TableCellRenderer...
Refer to the API docs here... http://docs.oracle.com/javase/1.4.2/docs/api/javax/swing/table/DefaultTableCellRenderer.html
You basically want to overwrite the getTableCellRendererComponent() method, and add in any additional code for rendering the image.
For example, to add an icon before the document, you would do the following...
public void MyTableCellRenderer extends DefaultTableCellRenderer {
public MyTableCellRenderer(){
super();
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column){
Component renderer = super.getTableCellRendererComponent(table,value,isSelected,hasFocus,row,column);
if (row == 0 && renderer instanceof JLabel){ // where row == 0 is the row you want to add the icon to
((JLabel)renderer).setIcon(new ImageIcon("image.png"));
}
return renderer;
}
}
You would need to set this as the TableCellRenderer for the column or table.
You would also do a similar thing for adding an image column to the table.
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);
}
});