0
public class UserPage extends JFrame implements ActionListener {

JTable table;
UserModel model;
private JButton addButton;

    public UserPage() {
    UserJDBC userJDBC = new UserJDBC();
    model = new UserModel(userJDBC.getData(), userJDBC.getColumn());
    table = new JTable(model);
    addButton = new JButton("Add User");
    addButton.addActionListener(this);
    add(addButton,BorderLayout.SOUTH);
    add(new JScrollPane(table), BorderLayout.CENTER);
    setVisible(true);
}
    @Override
public void actionPerformed(ActionEvent e) {
    if (e.getSource() == addButton) addAction();
}

    public void addAction() {
    AddUserDialog UserDialog = new AddUserDialog(this);
    model.addQuery(UserDialog.getfName(), UserDialog.getlName(), UserDialog.getGender(), UserDialog.getDate());
}

AddUserDialog Class:

public class AddUserDialog extends JDialog implements ActionListener {

    public AddUserDialog(JFrame owner) {
    super(owner, "New User", true);
    add(createForm(), BorderLayout.CENTER);
    setVisible(true);
    pack();
}

@Override
public void actionPerformed(ActionEvent e) {
     if (e.getSource() == okBtn) {
        okAction();
        this.dispose();
    }
}
    public void okAction() {
    setfName(fNameTf.getText());       // Get First name from text field
    setlName(lNameTf.getText());       // Get Last name from text field
    if (!genderSelection()) {          // Get gender as radio buttons
        return;
    }
    setDate(dateGenerate());          // Get date 
}

Model Class:

public class UserModel extends DefaultTableModel {

public UserModel(Vector<Vector<String>> data, Vector<String> column) {
    super(data, column);
}
    public void addQuery(String fname, String lname, String gender, String date) {
    try {
        Connection con;
        Statement statement;
        String query = "insert into UserTable(FirstName,LastName,Gender,Date) " +
                "values ( '" + fname + "' , '" + lname + "' , '" + gender + "', '" + date + "' ) ";
        con = DriverManager.getConnection(...);
        statement = con.createStatement();
        if (statement.execute(query)) {
            UserJDBC userJDBC = new UserJDBC();
            fireTableRowsInserted(userJDBC.getData().size() - 1, userJDBC.getData().size() - 1);
        }

    } catch (SQLException sqle) {
        sqle.printStackTrace();
    }
}
}

My JDBC Class:

public class UserJDBC {

Vector<String> column = new Vector<String>();
Vector<Vector<String>> data = new Vector<Vector<String>>();
Connection connection = null;
Statement statement;
ResultSet resultSet;

    public Vector<String> getColumn() {
          // get column correctly
    }

    public Vector<Vector<String>> getData() {
    try {
        connection = DriverManager.getConnection(...);
        statement = connection.createStatement();
        resultSet = statement.executeQuery("select * from Table");
        int c = resultSet.getMetaData().getColumnCount();

        while (resultSet.next()) {
            Vector<String> eachRow = new Vector<String>(c);
            for (int i = 1; i <= c; i++) {
                eachRow.add(resultSet.getString(i));
            }
            data.add(eachRow);
        }

    } catch (SQLException sqle) {
        sqle.printStackTrace();
    }
    return data;
}
}

Now When i want to add a new user, My GUI needs to be refresh to show new row!

Update:

public void addQuery(String fname, String lname, String gender, String date) {
    try {
        Connection con;
        Statement statement;
        String query = "insert into UserTable(FirstName,LastName,Gender,Date) " +
                "values ( '" + fname + "' , '" + lname + "' , '" + gender + "', '" + date + "' ) ";
        con = DriverManager.getConnection(...);
        statement = con.createStatement();
        if (statement.execute(query)) {
            Object[] addedRow = new Object[]{fname,lname,gender,date};
            Vector addedVector = new Vector();
            addedVector.addElement(addedRow);
            this.addRow(addedRow);        // this?
            this.addRow(addedVector);     // Or this?
        }

    } catch (SQLException sqle) {
        sqle.printStackTrace();
    }
}
Sajad
  • 2,273
  • 11
  • 49
  • 92
  • Could you please explain what you mean by your title? Also have a look at: http://stackoverflow.com/questions/3179136/jtable-how-to-refresh-table-model-after-insert-delete-or-update-the-data – PM 77-1 Sep 11 '13 at 18:53
  • 1
    -1, Why do you keep reinventing the wheel??? You have been told several times that the DefaultTableModel supports methods like remove(...) (which you have been playing with for weeks) and add(...). Read the API and use the appropriate method instead of trying to do it yourself. There is absolutely no need for you to use your UserJDBC class. How does creating a new UserJDBC class update the existing TableModel? Why can't you listen to things you have been told over the past month?????????? Quit wasting the time of everybody who reads all these unnecessary questions. – camickr Sep 11 '13 at 19:03
  • @camickr I know how create my JTable with ResultSetTableModel . This is a provided class. When use this class, every things is good and works perfectly. But, as you see my code, I want to create my own table model and other necessary classes to be quite fluent on this topic (`JTable). Do you think it is vain? Please convince me! – Sajad Sep 12 '13 at 09:42
  • You have no understanding of how a TableModel works. Why do create new UserJDBC?. How does that change the data in the current TableModel? It doesn't. All you have done is create two more Vectors in your program. These Vectors are in no way related to the TableModel that is being displayed in you JTable. ` I want to create my own table model and other necessary classes` - there is no need for other classes. You have been told you either 1) create a custom model or 2) create a helper class, NOT BOTH. For a month you haven't listened to my suggestions, so yes I think it is in vain. – camickr Sep 12 '13 at 14:50
  • @camickr Well, I know how TableModel works, e.g: for `remove()`, I should first remove from database, if done, then remove from table model by table model own remove method. and for `add()`, First i should add new record to database, Then i should refresh my table, and no need to add new element into model. Please tell me about i should `create two more Vectors in my program`, Why?! Thanks – Sajad Sep 12 '13 at 16:56
  • @camickr Please see update and tell me is this good way to add record to model? – Sajad Sep 12 '13 at 16:56
  • The addRow() method takes an Object array so I would use that method. Why would you create a Vector if you don't need to? – camickr Sep 12 '13 at 18:24
  • Because the addRow() method takes Object array and Object vector. (i see when i press ctrl+space in my IDE). So i try both ways. – Sajad Sep 12 '13 at 18:32
  • Is this the correct way of using this method? – Sajad Sep 12 '13 at 18:33

1 Answers1

4

don't to bother with, I'm sure that too hard to explain you consistency of..., simple shortcut

1.st level, usage

private ResultSetTableModel tableModel;
private String driver = "full.name.of.driver";
private String dbName = "databseName";
private String url = "jdbc:Xxx.databaseurl, additonal parameter if needed";
private String query = "SELECT * FROM mytablename";
private JTable resultTable; 

anywhere to initialize

try {
   tableModel = new ResultSetTableModel(driver, url, query);
} catch (SQLException ex) {
   // exception handling or JOptionPane
}
resultTable = new JTable(tableModel);

and/or refresh TableModel from void or JButtons Action

private void refreshTable(String query) {
    try {
            tableModel.setQuery(query);
    } catch (SQLException sqlException) {
            JOptionPane.showMessageDialog(null, sqlException.toString(), "SQL Exception", JOptionPane.ERROR_MESSAGE);
    }
}

AbstractTableModel

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import javax.swing.event.TableModelEvent;
import javax.swing.table.*;
// ResultSet rows and columns are counted from 1 and JTable
// rows and columns are counted from 0. When processing
// ResultSet rows or columns for use in a JTable, it is
// necessary to add 1 to the row or column number to manipulate
// the appropriate ResultSet column (i.e., JTable column 0 is
// ResultSet column 1 and JTable row 0 is ResultSet row 1).

public class ResultSetTableModel extends AbstractTableModel {

    private static final long serialVersionUID = 1L;
    private Connection connection;
    private Statement statement;
    private ResultSet resultSet;
    private ResultSetMetaData metaData;
    private int numberOfRows;
    // initialize resultSet and obtain its meta data object determine number of rows

    public ResultSetTableModel(String driver, String url,
            String query) throws SQLException, ClassNotFoundException {
        Class.forName(driver);// load database driver class        
        connection = DriverManager.getConnection(url);// connect to database
        // create Statement to query database
        statement = connection.createStatement(
                ResultSet.TYPE_SCROLL_INSENSITIVE,
                ResultSet.CONCUR_READ_ONLY);
        setQuery(query);// set query and execute it
    }

    @Override// get class that represents column type
    public Class<?> getColumnClass(int column) {// determine Java class of column        
        try {
            String className = metaData.getColumnClassName(column + 1);
            return Class.forName(className); // return Class object that represents className
        } // catch SQLExceptions and ClassNotFoundExceptions
        catch (Exception exception) {
            exception.printStackTrace();
        }
        return Object.class;// if problems occur above, assume type Object
    }

    @Override// get number of columns in ResultSet
    public int getColumnCount() {
        try { // determine number of columns
            return metaData.getColumnCount();
        } // catch SQLExceptions and print error message
        catch (SQLException sqlException) {
            sqlException.printStackTrace();
        }
        return 0; // if problems occur above, return 0 for number of columns
    }

    @Override // get name of a particular column in ResultSet
    public String getColumnName(int column) {
        // determine column name
        try {
            return metaData.getColumnName(column + 1);
        } // catch SQLExceptions and print error message
        catch (SQLException sqlException) {
            sqlException.printStackTrace();
        }
        return "";// if problems, return empty string for column name
    }

    @Override// return number of rows in ResultSet
    public int getRowCount() {
        return numberOfRows;
    }

    @Override // obtain value in particular row and column
    public Object getValueAt(int row, int column) {
        try {  // obtain a value at specified ResultSet row and column
            resultSet.absolute(row + 1);
            return resultSet.getObject(column + 1);
        } // catch SQLExceptions and print error message
        catch (SQLException sqlException) {
            sqlException.printStackTrace();
        }
        fireTableCellUpdated(row, column);
        return "";// if problems, return empty string object
    }

    @Override // close Statement and Connection
    protected void finalize() {
        try { // close Statement and Connection
            statement.close();
            connection.close();
        } // catch SQLExceptions and print error message
        catch (SQLException sqlException) {
            sqlException.printStackTrace();
        }
    }

    // *******set new database query string*********
    public void setQuery(String query) throws SQLException {
        // specify query and execute it
        resultSet = statement.executeQuery(query);
        // obtain meta data for ResultSet
        metaData = resultSet.getMetaData();
        // determine number of rows in ResultSet
        resultSet.last();                   // move to last row
        numberOfRows = resultSet.getRow();  // get row number
        // notify JTable that model has changed
        fireTableStructureChanged();
        fireTableChanged(null);
    }

    public void tableChanged(TableModelEvent e) {
        fireTableChanged(e);
    }
}

2nd. compare you code with this basic stuff, e.g. see connection (very long and hard operation is always opened), really this is not good idea

note never to call fireWhatever in DefaultTableModel, those notifiers are implemented and correctly, you are an issue with Concurency in Swing

mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • note some Database engines doesn't implements Cursor --> `resultSet.last();` – mKorbel Sep 11 '13 at 19:11
  • add, remove, update row in database as separate process, then to call tableModel.setQuery(query); – mKorbel Sep 11 '13 at 19:24
  • I wonder why you're not to blame me for the repetitive question! – Sajad Sep 12 '13 at 09:35
  • I know how create my JTable with `ResultSetTableModel` . This is a provided class. When use this class, every things is good and works perfectly. But, as you see my code, I want to create my own table model and other necessary classes to be quite fluent on this topic (`JTable). Do you think it is vain? Please convince me! – Sajad Sep 12 '13 at 09:40
  • UserModel.add(eachRow); – mKorbel Sep 12 '13 at 16:35
  • What mean `UserModel.add(eachRow);`? – Sajad Sep 12 '13 at 16:37
  • DefaultTableModel (as camickr already and repeatly commented) has implemented this method, you don't need to recreate underlaing array for table model, otherwise you have to notify model taht array was changed, otherwise is there still old one – mKorbel Sep 12 '13 at 16:40
  • Well, So for add a new record, I know that i should add into my database, Should i add it into my model? Or it is no need? because i think that all vectors arr filled with database and after a `fireXxx` new row will display! – Sajad Sep 12 '13 at 16:43
  • Please see update and tell me is this good way to add record to model? – Sajad Sep 12 '13 at 16:55
  • this.addRow(addedrow); where replace this with local variable for JTable or DefaultTableModel – mKorbel Sep 12 '13 at 16:59
  • delete `this`? It use method arguments! Please say simple!! – Sajad Sep 12 '13 at 17:02
  • myTableModelLocalVariableName.addRow(addedrow); – mKorbel Sep 12 '13 at 18:19
  • You say me on previous question that: `The code to update the database and the model should be executed in the same method`. So is your mean that i should override defaultTableModel method to add my `JDBC` codes? Or put `JDBC` codes in a separate method? Which is better? – Sajad Sep 12 '13 at 19:46
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/37287/discussion-between-a-polite-boy-and-mkorbel) – Sajad Sep 12 '13 at 21:34