Link to home
Start Free TrialLog in
Avatar of Omer-Pitou
Omer-Pitou

asked on

JTable: Edit Colums

Dear sirs,
I am trying to achieve this:
- Having a JTable where the user can enter data. Only few columns will be editable.
- Controlling the input: Setting up a min value and a max value, as this works for spinner model.
- Which listener can I implement to track these change.

I made the columns editable available by overridding the isCellEditable method of the Table model, unfortunately  everytime I type something, the content is just cleared, after pressing Enter.

Any guidance, any tutorial, or any working example, on how this can be implemented, will be highly appreciated.

Regards
Avatar of Maidine Fouad
Maidine Fouad
Flag of Morocco image

Try this whitout overrriding the method

JTable table = new JTable();
...
table.setEnabled(True);

Open in new window

Avatar of Omer-Pitou
Omer-Pitou

ASKER

HI Fouad,
Sorry this doesn't work
This is my custom table model used to load my JTable, it works perfectly.
For some  interfaces, I have to offer a way to enter data into the JTable cell.
I tried several times without success.  The column is already editable, and I can type inside. Unfortunately when I press ENTER, the data entered disappears.
I don't know what I am doing wrong.

package com.finger.general.classes;

import com.opencsv.CSVWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import javax.swing.JOptionPane;
import javax.swing.table.AbstractTableModel;

public final class MyTableModel extends AbstractTableModel {
    
    private ResultSetMetaData modelMetaData;
    private ResultSet modelResultSet;
    private MyDataAccessObject oDAO;
    private PreparedStatement modelPrepStmt;
    private final boolean isPrepStmt;
    private boolean isModelEditable=false;
    
    private int editColumn;
    
    private String defaultStmt;
    private String modelQueryStmt;
        
    private final MyDictionary oDictionary = new MyDictionary();
        
    public MyTableModel (String pSQLStmt) {
        super();
        this.isPrepStmt = false;
        this.defaultStmt = pSQLStmt;
        this.modelQueryStmt = this.defaultStmt;
        populateData(getResultSet(this.isPrepStmt));
    } 
    
    public MyTableModel (PreparedStatement pPrepStmt) {
        super();
        this.isPrepStmt = true;
        this.modelPrepStmt = pPrepStmt;
        populateData(getResultSet(this.isPrepStmt));
    } 
    
    public MyTableModel (PreparedStatement pPrepStmt, boolean pEditable, int pEditColumn) {
        super();
        this.isModelEditable = pEditable;
        this.editColumn = pEditColumn;
        this.isPrepStmt = true;
        this.modelPrepStmt = pPrepStmt;
        populateData(getResultSet(this.isPrepStmt));
    } 
    
    private ResultSet getResultSet(boolean pIsPrepStmt) {
        if (oDAO == null) {
            oDAO = new MyDataAccessObject();
        }
        if (pIsPrepStmt) {
            try {
                return modelPrepStmt.executeQuery();
            } catch (SQLException ex) {
                JOptionPane.showMessageDialog(null, ex.getMessage(),oDictionary.getErrorTitle(), JOptionPane.ERROR_MESSAGE);    
            }
        } else {
            return oDAO.executeQuery(this.modelQueryStmt);  
        }  
        return null;
    }
    
    private void populateData(ResultSet pResultSet) {
        try {
            modelResultSet = pResultSet;
            modelMetaData = modelResultSet.getMetaData();
                                           
            this.fireTableDataChanged();
            
        } catch (SQLException ex) {
            JOptionPane.showMessageDialog(null, ex.getMessage(),oDictionary.getErrorTitle(), JOptionPane.ERROR_MESSAGE);
        }            
    }
        
    public void refreshData() {
        this.modelQueryStmt = this.defaultStmt;
        this.populateData(getResultSet(this.isPrepStmt));
    }
    
    public void exportData(boolean pIsPrepStmt) {
        String cFilePath = new MyFileIO().getSaveToFilePath("csv");
        if (! cFilePath.isEmpty()) {
            try {
                CSVWriter writer;
                modelResultSet = getResultSet(pIsPrepStmt);
                writer = new CSVWriter(new FileWriter(cFilePath, true));
                writer.writeAll(modelResultSet, true);
                writer.flush();
                writer.close();
                JOptionPane.showMessageDialog(null, oDictionary.getConfirmationExportMessage(), oDictionary.getConfirmationTitle(),
                        JOptionPane.INFORMATION_MESSAGE);

            } catch (IOException | SQLException ex) {
                JOptionPane.showMessageDialog(null, ex.getMessage(),oDictionary.getErrorTitle(), JOptionPane.ERROR_MESSAGE);
            } 
        }       
    }
              
    public void disconnectFromDB() {
        try {
            if (modelResultSet != null) {
                modelResultSet.close();
            }
            if (modelPrepStmt != null) {
                modelPrepStmt.close();
            }
            if (oDAO != null) {
                oDAO.closeConnection();
            }
        } catch (SQLException sqlException) {
            JOptionPane.showMessageDialog(null, sqlException.getMessage(), oDictionary.getErrorTitle(), JOptionPane.ERROR_MESSAGE);
        }    
    }        

    //Native methods
    @Override
    public Class getColumnClass(int column) {
        try {
            String className = modelMetaData.getColumnClassName(column + 1);
            return Class.forName(className);
        } catch (SQLException | ClassNotFoundException exception) {
            JOptionPane.showMessageDialog(null, exception.getMessage(),oDictionary.getErrorTitle(), JOptionPane.ERROR_MESSAGE);
        }
        return Object.class;
    }   
    
    @Override
    public int getColumnCount() {
        try {
            return modelMetaData.getColumnCount();
        } catch (SQLException sqlException) {
            JOptionPane.showMessageDialog(null, sqlException.getMessage(), oDictionary.getErrorTitle(), JOptionPane.ERROR_MESSAGE);
        }
        return 0;
    } 
    @Override
    public String getColumnName(int column) {
        try {
            return modelMetaData.getColumnName(column + 1);
        } catch (SQLException sqlException) {
            JOptionPane.showMessageDialog(null, sqlException.getMessage(),oDictionary.getErrorTitle(), JOptionPane.ERROR_MESSAGE);
        }
        return "";
    }   
    @Override
    public int getRowCount() {
        try {
            modelResultSet.last();
            return modelResultSet.getRow();
        } catch (SQLException ex) {
            JOptionPane.showMessageDialog(null, ex.getMessage(),oDictionary.getErrorTitle(), JOptionPane.ERROR_MESSAGE);           
        }
        return 0;            
    }
    @Override
    public Object getValueAt(int row, int column) {
        try {
            modelResultSet.absolute(row + 1);
            return modelResultSet.getObject(column + 1);
        } catch (SQLException sqlException) {
            JOptionPane.showMessageDialog(null, sqlException.getMessage(),oDictionary.getErrorTitle(), JOptionPane.ERROR_MESSAGE);
        }
        return null; // ""
    }    
   
    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        if (this.isModelEditable) {
            if (columnIndex == this.editColumn) {
                return true;
            }
        }
        return super.isCellEditable(rowIndex, columnIndex);
    }
   
    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        super.setValueAt(aValue, rowIndex, columnIndex);    
        super.fireTableCellUpdated(rowIndex, columnIndex);
        
    }
      
}

Open in new window


Thank you in advance for your help.
Avatar of zzynx
First a remark (unrelated to your problem): I would use the same condition that you use in the method isCellEditable() also in the method setValueAt()

Question: when you run in debug mode, do you trigger/reach your setValueAt() method?

Could you post a small, runnable program that uses your table model to demonstrate your problem?

Some examples that can help you:
http://www.java2s.com/Tutorial/Java/0240__Swing/DemonstratestheeditablepropertyofSwingtables.htm
http://www.codejava.net/java-se/swing/editable-jtable-example
Thanks for the remark.
I didn't run it in debug mode.
What I did to find the problem is that I added System.out lines and realized aValue, rowIndex, columnIndex were showing the right values. Still don't understand why they disappear after ENTER is pressed.
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        System.out.println(aValue);
        System.out.println(rowIndex);
        System.out.println(columnIndex);      
    
        super.setValueAt(aValue, rowIndex, columnIndex);    
        super.fireTableCellUpdated(rowIndex, columnIndex);
        
    }

Open in new window


I can make a small program from the current one to demonstrate that.
Briefly this is the code that loads the table
//Liste Prix
        oPrixTableModel = prixmodel.getFilterTableModel(view.getMagasinID().getText(), view.getCategorieID().getText(),
                view.getArticleID().getText(), view.getActifprix().isSelected(), view.getSearchprix().getText());
        view.getMyTablePrix().setModel(oPrixTableModel);

Open in new window

It takes the table model from the custom table model previously posted
I can make a small program from the current one to demonstrate that.
That would be interesting. Then I can run it too and hunting down the mistake, if any.
Hi zzynx,
From this link you just gave me

How I can make this example use The ResultSet to create the table model, instead String[] for column names and Object[][] for rows.  Especially for setValueAt method. That where the problem  is
From this link you just gave me
Which one of the links?
ASKER CERTIFIED SOLUTION
Avatar of zzynx
zzynx
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I try this tomorrow and let you know.
I changed to List, and it works. THANK YOU.
I want an advice on the Listener to implement here in order to track the changes. Should I implement TableModelListener or KeyListener (on JTable itself)
You're welcome. Thanx 4 axxepting.
In order to track changes to your table data you should use TableModelListener