SetValueAt Never Called in my table model

Hi my experience in Java is limited so please excuse my ignorance.

I created a table by doing this:

private JTable table =new JTable(model);

where model is a custom table model that extends AbstractTableModel.

Anyhow, It was to my understanding that if my cells were made editable through theisCellEditable method, then I could double click on a cell, change its value and after I hit enter or deselect the cell SetValueAt would be called. This isn't happening, so can someone tell me what I have to do to get this method called when the user does this?

Thanks

Andy

[688 byte] By [Lokkea] at [2007-10-3 2:49:24]
# 1

Actually, setValueAt() is a method that you call from within the code to set the value of a cell.

To detect when a value is set by the user, you need to write an event handler. Read up here: http://java.sun.com/docs/books/tutorial/uiswing/events/index.html

You will need to implement the java.swing.event.TableModelListener interface.

myjavasticka at 2007-7-14 20:38:11 > top of Java-index,Desktop,Core GUI APIs...
# 2

No luck.

I added the tablemodellistener by adding addTableModelListener(this);

to my constructor of my tablemodel. and adding a tableChanged method to the model.

However, tableChanged is not being called when the user selects a cell and tries to change it. While it is called when I add a row to the table and such, that is not what I am looking for.

What listener am I trying to find that would do this?

Lokkea at 2007-7-14 20:38:11 > top of Java-index,Desktop,Core GUI APIs...
# 3
Is the value changing in the table?
zadoka at 2007-7-14 20:38:11 > top of Java-index,Desktop,Core GUI APIs...
# 4

> Anyhow, It was to my understanding that if my cells were made

> editable through the isCellEditable method, then I could double click

> on a cell, change its value and after I hit enter or deselect the cell SetValueAt would be called.

That is correct.

There is no need to use a TableModelListener to have the table updated. The setValueAt(...) method should be called by the editor.

Why do you feel you need extend AbstractTableModel? By default this class doesn't do anything in the implementation of setValueAt(...) so the data won't be saved unless you've added custom code. Just use the DefaultTableModel and save yourself a lot of trouble.

If you need further help then you need to create a [url http://homepage1.nifty.com/algafield/sscce.html]Short, Self Contained, Compilable and Executable, Example Program[/url] that demonstrates the incorrect behaviour, because I can't guess exactly what you are doing based on the information provided.

And don't forget to use the [url http://forum.java.sun.com/help.jspa?sec=formatting]Code Formatting Tags[/url] so the code retains its original formatting.

camickra at 2007-7-14 20:38:11 > top of Java-index,Desktop,Core GUI APIs...
# 5

Ok thank you everyone for your responses, I'm going to post some code.

Zadok, in response to your question if I understand you correctly the numbers are changing in the table, until I hit enter then it returns back to what it was.

Alot of the code isn't my own but from what I've pieced together from different sites. There are 3 files, the MyTableModel2, which uses a list to hold the data. The list holds "Part" components which is defined in Part class, andthen DemoProject which creates the table and and what not.

DemoProject.java

import javax.swing.*;

import java.awt.*;

public class DemoProject {

final static String LOOKANDFEEL = null;

private MyTableModel2 model = new MyTableModel2();

private JTable table = new JTable(model);

public DemoProject(){

Part temp = new Part();

temp.SetId(1);

temp.SetX(2);

temp.SetY(3);

model.add(temp);

}

public Component createComponents() {

//INITIALIZE TABLE

table.setPreferredScrollableViewportSize(new Dimension(200, 50));

JScrollPane scrollPane = new JScrollPane(table);

//INITIALIZE PANEL

JPanel pane = new JPanel(new GridLayout(0, 1));

pane.add(scrollPane);

return pane;

}

private static void createAndShowGUI() {

//Make sure we have nice window decorations.

JFrame.setDefaultLookAndFeelDecorated(true);

//Create and set up the window.

JFrame frame = new JFrame("test");

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

DemoProject app = new DemoProject();

Component contents = app.createComponents();

frame.getContentPane().add(contents, BorderLayout.CENTER);

//Display the window.

frame.pack();

frame.setVisible(true);

}

public static void main(String[] args) {

javax.swing.SwingUtilities.invokeLater(new Runnable() {

public void run() {

createAndShowGUI();

}

});

}

}

Ok now MyTableModel2.java

import java.util.List;

import java.util.ArrayList;

import javax.swing.table.AbstractTableModel;

import javax.swing.event.*;

//import javax.swing.CellEditor;

public class MyTableModel2 extends AbstractTableModel implements TableModelListener {

private static final long serialVersionUID = 224343431;

private static final String columnNames[] = {

"Vertex #", "X", "Y"

};

private List<Part> parts = new ArrayList<Part>();

public MyTableModel2()

{

addTableModelListener(this);

}

public void setParts( List<Part> parts ) {

if ( parts == null )

throw new IllegalArgumentException("Cannot set null parts");

this.parts = parts;

fireTableDataChanged(); // notify listeners

}

public void add( Part part ) {

part.SetId(parts.size()+1);

int ix = parts.size();

parts.add( part );

fireTableRowsInserted( ix, ix ); // notify listeners

}

public void add( List<Part> partList ) {

int n = partList.size();

if ( n == 0 )

return;

int ix = parts.size();

parts.addAll( partList );

fireTableRowsInserted( ix, ix + n - 1 );

}

public void remove( int row ) {

parts.remove( row );

fireTableRowsDeleted( row, row );

}

public Part getPrevious()

{

if (parts.size() >= 2)

{

return parts.get(parts.size()-2);

}

else return null;

}

// Implementation of TableModel's methods

public String getColumnName( int col ) {

return columnNames[col];

}

public int getColumnCount() {

return columnNames.length;

}

public int getRowCount() {

return parts.size();

}

public Object getValueAt( int row, int col ) {

Part part = parts.get(row);

switch ( col ) {

case 0: return part.getId();

case 1: return part.getX();

case 2: return part.getY();

}

return null;

}

public boolean isCellEditable(int row, int col) {

//Note that the data/cell address is constant,

//no matter where the cell appears onscreen.

if (col < 1) {

return false;

} else {

return true;

}

}

public void setValueAt(int value, int row, int col) {

System.out.println("setValueAt called");

Part part = parts.get(row);

switch (col) {

case 1: part.SetX(value); break;

case 2: part.SetY(value); break;

}

parts.remove(row);

parts.add(row, part);

fireTableCellUpdated(row, col);

}

public void tableChanged(TableModelEvent e)

{

System.out.println("tableChanged called");

return;

}

}

and Finally Part.java

public class Part {

private int id;

private int x;

private int y;

public int getId(){

return id;

}

public int getX(){

return x;

}

public int getY(){

return y;

}

public String getName()

{

return "Part";

}

public void SetId (int input) {

this.id = input;

}

public void SetX (int input) {

this.x = input;

}

public void SetY (int input) {

this.y = input;

}

}

Again, what I'm looking for is a solution so that setValue method in the MyTableModel2 class is called whenever the user changes the cell value.

I didn't use DefaultTable because I wanted to use a list to hold the model data, and I figured it would be good experience?

Lokkea at 2007-7-14 20:38:11 > top of Java-index,Desktop,Core GUI APIs...
# 6
You didn't override the setValueAt(...) method. You created an new setValueAt(...) method.The method takes an Object as a parameter not an int.Same with getValueAt(...).See how much faster we can help when code is posted.
camickra at 2007-7-14 20:38:11 > top of Java-index,Desktop,Core GUI APIs...
# 7
Thanks for the extremely fast response, works like a charm now. *Slaps head*
Lokkea at 2007-7-14 20:38:11 > top of Java-index,Desktop,Core GUI APIs...