0

I have written a GUI Java program that manages a MySQL database. The user selects which columns (which tables and columns will be selected from the database) he/she wants to populate the JTable with.

I hard-coded the column names for the JTable so even if the user chooses to only display the data from a subset of columns, all of the column-names will be visible.

The problem is that when the user chooses columns in a different order than my JTable is anticipating, the data gets displayed in the wrong column.. It's a bit hard to explain so here's a screenshot of the genre data being loaded into the length column:

As you can see, it displays the genre data in the length column

tableGenerator class:

package gui;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Vector;

public class TableGenerator
{

    private ArrayList columnNames = new ArrayList();
    private ArrayList data = new ArrayList();
    private Vector columnNamesVector = new Vector();
    private Vector dataVector = new Vector();
    private int columns = 0;
    private int rows = 0;

    @SuppressWarnings("unchecked")
    public TableGenerator(ResultSet rs)
    {
        try{
            ResultSetMetaData md = rs.getMetaData();
            columns = md.getColumnCount();
            //  Get column names

                columnNames.add("Title");
                columnNames.add("Year");
                columnNames.add("Length");
                columnNames.add("Genre");
                columnNames.add("Actor");
                columnNames.add("Producer");
                columnNames.add("Director");
                columnNames.add("Writer");

            //  Get row data
            while (rs.next())
            {
                ArrayList row = new ArrayList(columnNames.size());

                for (int i = 1; i <= columns; i++)
                {
                        row.add(rs.getObject(i));
                }
                data.add( row );
                rows++;
            }
        }
        catch (SQLException e)
        {
            System.out.println( e.getMessage() );
        }

        // Create Vectors and copy over elements from ArrayLists to them
        // Vector is deprecated but I am using them in this example to keep 
        // things simple - the best practice would be to create a custom defined
        // class which inherits from the AbstractTableModel class


        for (int i = 0; i < data.size(); i++)
        {
            ArrayList subArray = (ArrayList)data.get(i);
            Vector subVector = new Vector();
            for (int j = 0; j < subArray.size(); j++)
            {
                subVector.add(subArray.get(j));
            }
            dataVector.add(subVector);
        }

        for (int i = 0; i < columnNames.size(); i++ )
            columnNamesVector.add(columnNames.get(i));
        }

    public Vector getColumns(){
        return columnNamesVector;
    }
    public Vector getData(){
        return dataVector;
    }
    public ArrayList getColumnNames(){
        return columnNames;
    }
    public int getNumberOfRows(){
        return rows;
    }

}

I'm using the DefaultTableModel with some modifications.. :

model = new DefaultTableModel(rows, columns){

    private static final long serialVersionUID = 1L;

    @Override
    public boolean isCellEditable(int row, int column) {
        return false;
    }

    @Override
    public Class<?> getColumnClass(int column) {
        if (column < classes.length) 
            return classes[column];
        return super.getColumnClass(column);

    };};
2
  • 1
    If this were my code, I'd solve it by not hard-coding the column names. You don't show us your table model class, something that I believe would be key towards solving this dilemma. Commented Aug 11, 2015 at 16:22
  • I'm using the DefaultTableModel with some modifications to enable sorting of integers and to disable editing, added it to the question. Commented Aug 11, 2015 at 16:26

1 Answer 1

2

Your query should always return the data for all columns. This means the data will be stored in the same manner in the TableModel.

You can then change the view for the columns to be displayed. That is you can remove TableColumns from the TableColumnModel of the JTable and only the data the user want to view will be displayed, even though it is still available in the model. Then means the user can click on any check box at any time and you don't need to redo the database query, only add the TableColumn back to the table.

Check out Table Column Manager for an example of this approach. This class uses a popup menu to manage the columns, but you can still use your check boxes. You just need to invoke the appropriate method of the TableColumnManager to hide/show a column. That is, assuming the labels of the check boxes match the headings in the table you can just use the check box text to hide/show a column.

The other approach is to NOT hard code the column names (if you build your query to only get specific columns) but instead get the column names from the meta data of the ResultSet. The TableFromDatabaseExample.java from Table From Database shows how this can be done. The code is generic so that appropriate renderers are used for Dates, Integers etc.

Sign up to request clarification or add additional context in comments.

1 Comment

Alright, I will check out the Table Column Manager, thank you :) I did not hard code the column names before and it was working very good. The problem was that when I edited the table and saved the data to the database..because then I needed the data of the other fields in my WHERE statement.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.