JTable's setValueAt() method is not updating cell data - java

I have created a JTable using Abstract Table Model. This table has a two dimensional array of Integer object data and one 1 dimensional column header.Everything works fine except when I edit & change the cell data during program's runtime, it reverts back to the default value (created with getValueAt()). I have implemented Abstract Table Models setValueAt() method but it does not work.
Can anyone please tell me whats is wrong in my code?
import javax.swing.table.AbstractTableModel;
public class TableModel1 extends AbstractTableModel {
/**
*
*/
private static final long serialVersionUID = 1L;
String [] colNames=new String[30];
Object[][] data= new Integer[4][30];
#Override
public int getColumnCount() {
return colNames.length;
}
#Override
public int getRowCount() {
return 4;
}
public String getColumnName(int col){
if (col==0){
colNames[0]="Boarders";
}
else if(col>0){
for(int i=1;i<colNames.length;i++){
colNames[i]=new String(""+i);
}
}
return colNames[col];
}
#Override
public Object getValueAt(int row, int col) {
for(int i=0; i<data.length;i++){
for(int j=0; j<data[i].length;j++){
data[i][j]=new Integer(1);
}
}
return data[row][col];
}
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
public boolean isCellEditable(int row, int col){
return true;
}
public void setValueAt (Object aValue, int row, int col){
data[row][col]=(Integer)aValue;
fireTableCellUpdated(row,col);
}
}//end class

Seems that happens because when getValueAt() method invokes, you always refresh data in your array with next lines:
for(int i=0; i<data.length;i++){
for(int j=0; j<data[i].length;j++){
data[i][j]=new Integer(1);
}
}
So, remove this lines from getValueAt() method, and initialize your array in constructor of your model only once not every time as now.

the problem is in the getValueAt . those methods are constantly called. its not a one time thing. initiate the values outside of the table model

Related

Create custom table model with column header in java

I'm developing a software for my friend.I have developed 90% of my project and my problem is I have a table which I fill with data in database.I have used a custom table model to fill jtable. It fills data perfectly but the problem is it doesn't contain proper column header instead of that it contain A,B,C for column headers .
here is my custom table model class.
public class SellUpdateModel extends AbstractTableModel
{
private Vector<Vector> data;
public SellUpdateModel(String Jid)
{
data = new Vector<>();
data = new JobDetailsDAO().get_ItemDescriptionAndQuantity(Jid); //Retrive data from databse and fill it to vector.
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex)
{
return false; // does not allowed to edit cells
}
#Override
public int getRowCount()
{
return data.size();
}
#Override
public int getColumnCount()
{
return 3;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex)
{
return data.elementAt(rowIndex).elementAt(columnIndex);
}
public SellUpdateModel deleteRow(int row, Vector pData)
{
data.remove(data.elementAt(row)); // remove a record from vector
data.add(pData); // add a record to vector
return this;
}
}
You have to override getColumnName(int columnIndex).
public class SellUpdateModel extends AbstractTableModel {
private final String[] tableHeaders = {"X", "Y", "Z"};
#Override
public String getColumnName(int columnIndex) {
return tableHeaders[columnIndex];
}
}

TableModel - Doesn`t show anything in the gui?

I am fetching the data from the DAO to the GUI level.
When I want to load the Table I get an empty table only with the right row count of the clicked db symbol:
To load the elements I use:
playlistTable.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 1) {
JTable target = (JTable)e.getSource();
int row = target.getSelectedRow();
playlistTableModel.setPlaylists(playlistService.getMoviesOfPlaylist(row));
}
Why is the Table empty?
UPDATE
Table model code:
public class PlaylistTableModel extends AbstractTableModel {
/**
* Generated UID
*/
private static final long serialVersionUID = 9058516120594137393L;
/**
* List of playlist to be shown
*/
private List<Playlist> playlist;
public PlaylistTableModel(List<Playlist> playlist){
this.playlist=playlist;
}
public int getColumnCount() {
return 1;
}
public int getRowCount() {
return playlist.size();
}
public Object getValueAt(int arg0, int arg1) {
Playlist playlists = playlist.get(arg0);
switch(arg1){
case 0: return playlists.getName();
default: return null;
}
}
public void setPlaylists(List<Playlist> playlist){
this.playlist=playlist;
fireTableDataChanged();//Aktualisiert Playlist automatisch
}
public void setPlaylist(Playlist playlists){
playlist.add(playlists);
fireTableRowsInserted(playlist.size()-1, playlist.size()-1);
}
public String getColumnName(int column) {
if(column==0){
return "Playlist";
}
else{
return null;
}
}
/**
* Returns a movie from the list specified by the index
* #param row index of the movie
* #return movie
*/
public Playlist getPlaylist(int row){
return playlist.get(row);
}
#Override
public boolean isCellEditable(int row, int col) {
return true;
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex){
if(columnIndex!=0){
return;
}
fireTableCellUpdated(rowIndex, columnIndex);
}
This method may be the problem,
public void setPlaylist(Playlist playlists){
playlist.add(playlists);
fireTableRowsInserted(playlist.size()-1, playlist.size()-1);
}
Here for example if we got the playlists with size 20. Then after assigning to the table model playlist you are calling,
fireTableRowsInserted(playlist.size()-1, playlist.size()-1);
which will reduce to,
fireTableRowsInserted(19, 19);
But actually what has happened is we are not just inserting one row but 20 rows. So as suggested by #Ivan.Latysh in the answer section, you need to call insert from the start of the row count to the end of the row count. This will repaint the inserted rows.
P.S: You can simply call fireTableDataChanged(); method also. But this method will repaint entire table. Prefer this method only if the entire table list is changed. Else you have respective fireXX methods for Insertion, Update, Delete.
Probably issue is in getValueAt method, change like this
public Object getValueAt(int arg0, int arg1) {
// since you use only one column
return playlist.get(arg0).getName();
}
The issue is that you are firing a wrong change event
fireTableRowsInserted(playlist.size()-1, playlist.size()-1);
Docs state:
public void fireTableRowsInserted(int firstRow,
int lastRow)
Notifies all listeners that rows in the range [firstRow, lastRow], inclusive, have been inserted.
So if you want to be optimal, do this:
public void setPlaylist(Playlist playlists){
int firstRow = playlist.size();
playlist.add(playlists);
fireTableRowsInserted(firstRow, playlist.size()-1);
}
Or simply re-draw entire table. Don't forget that table also may re-calculate its sizes.
fireTableDataChanged();

Output the content of a LinkedHasHSet into a JTable

I have a LinkedHashSet of Book objects. The Book objects have the following fields:
private int id;
private String author = "";
private String title = "";
private boolean isRead;
private String dateStamp = "";
private static int counter = 0;
I want them to go into my JTable which has the following columns:
String [] columnNames = {"ID","Title", "Author", "Status", "Date Read"};
How can I do this? And is it possible to have the isRead field being editable through a checkbox in the table?
You need to have a class that extends AbstractTableModel. This class should use your LinkedHashSet as the data source for your table. The basic implementation provided by AbstractTableModel should suit most of your needs. If not, then you can override the methods you need to customize.
This tutorial should help you understand how JTable objects work.
This is a sample model I have created for the table.
public class CustomModel extends AbstractTableModel {
private Object[] colNames ={"ID","Title", "Author", "Status", "Date Read"};
private LinkedHashSet<CustomClass> data;
public TableModelTop() {
this.data = getDataForDropList();
}
public int getRowCount() {
return data.size();
}
public int getColumnCount() {
return colNames.length;
}
#Override
public String getColumnName(int columnIndex) {
return (String) colNames[columnIndex];
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
// Set Values here;
}
public Object getValueAt(int rowIndex, int columnIndex) {
// Get row Values here;
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
#Override
public Class<?> getColumnClass(int columnIndex) {
// Depending on the type of the column. Return data type;
}
/**
* Populate the data from here.
* #return LinkedHashSet<CustomClass>
*/
private LinkedHashSet<CustomClass> getDataForDropList() {
LinkedHashSet<CustomClass> modelList = new LinkedHashSet<CustomClass>();
for(int i = 0; i< 5; i++) {
// Create custom Object and add them to the LinkedHashSet.
// Create a CustomClass object and add it to the LinkedHashSet
modelList.add(customClassObject);
}
// Finally return the llinkedhashset
return modelList;
}
}
After this just call the table model and assign this to the JTable.
JTable table = new JTable(new CustomModel());
As a concrete example of using AbstractTableModel, you can leverage the toArray() method inherited by LinkedHashSet to simplify the implementation of getValueAt(), as shown in this related EnvTableTest. The default JTable renderer and editor use JCheckBox for TableModel elements of type Boolean.class, as shown in this example.

assign a hidden value to each row of jTable

How can I assign an id to each row of jTable?
I don't want user be able to see it.
A quick hack is just to use a hidden column. A better method may be to write a custom table model that doesn't even expose said data to the JTable, but that is more involved :-)
Happy coding.
You should implement your own table model by creating a class that implements TableModel, or perhaps more easily create a class that extends AbstractTableModel.
If you do that then, you only need to implement
class MyModel extends AbstractTableModel {
public Object getValueAt(int rowIndex, int columnIndex) {
// return what value is appropriate
return null;
}
public int getColumnCount() {
// return however many columns you want
return 1;
}
public int getRowCount() {
// return however many rows you want
return 1;
}
}
typically you would create a List in the class of object of your choosing, and getRowCount would just be how big the list was.
getValueAt would return values from the Object in the list.
for instance If i wanted a table of users with a hidden id, it would be
class UserModel extends AbstractTableModel {
private List<User> users = new ArrayList<User>();
public Object getValueAt(int rowIndex, int columnIndex) {
User user = users.get(rowIndex);
if (columnIndex == 0)
return user.getName();
else
return user.getAge(); //whatever
}
public int getColumnCount() {
return 2;
}
public int getRowCount() {
return users.size();
}
}
class User {
private int userId; // hidden from the table
private String name;
private int age;
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
rowData is just an Object array, so in your class that represents a row model have an member variable for id which won't be included in toString().

HowTo Remove a Row in a JTable with a Custom TableModel

I've been reading posts similar to mine, and reading through the Java tutorial page but I just can't seem to get this working. I'm not sure if I'm missing something fundamental or not...
I have a custom table model below that I need to be able to delete rows from. The table is initialized empty and rows are added through a combo box and an add button. There is also a delete button that needs to delete the selected row out of the table.
class TableModel extends AbstractTableModel
{
private String[] columnNames = {"Enabled", "Value" };
protected Class[] columnClasses = new Class[] { Boolean.class, String.class };
public int getColumnCount() { return columnNames.length; }
public int getRowCount() { return filters.size(); }
public String getColumnName(int col) { return columnNames[col]; }
public Class getColumnClass(int col) { return columnClasses[col]; }
public Object getValueAt(int row, int col) { ... }
public void setValueAt(Object value, int row, int col) { ... }
public void addRow(String value)
{
fireTableRowsInserted(filters.size() - 1, filters.size() - 1);
int row = filters.size() -1 ;
int col = 1;
setValueAt(value, row, col);
}
public void removeRow(int row)
{
fireTableRowsDeleted(selectedRow, selectedRow);
}
}
I have confirmed that selectedRow contains the correct row through prints in the console. The fireTableRowsDeleted function just doesn't do anything. The row still exists. How do you just delete a specific row?
Thanks,
The call to fireTableRowsDeleted simply fires off the event to indicate rows have been deleted, you still need to actually remove them from the model.
Immediately after I posted this I figured it out.
The rows contents are based on a List of filters:
public int getRowCount() { return filters.size(); }
My problem was I was trying to delete a row without removing that from the list. So I modified removeRow() to be the following:
public void removeRow(int row)
{
filters.remove(row);
fireTableRowsDeleted(row, row);
}
And it works like a charm.
cheers
I think this is the answer:
final int row = selectedRow;
EventQueue.invokeLater(new Runnable() {
public void run() {
model.removeRow(row);
}
});
The row will be deleted when the editing is finished.

Categories

Resources