1
votes

So I have been reading through Java's "How to use Tables" as I am trying to implement a JTable into my program. What I want is to take a list of String values from a database and then sort them by column and row names. Now I know there isn't a default row Header like there is for column's so I have been sidestepping this by making my first column a "row header". So then I decided to create a custom Table Model for my Jtable in order to sort the data correctly (the data is stored in a Vector of Vectors of Strings & column/row names as a Vector of Strings separately) but all I have been running into is problems. At first I was receiving a whole bunch of array out of index errors, so I added in code that showed me where data from the table model was being put in the Jtable. So here is the code from my Jpanel that initializes my Jtable

    //other GUI stuff above: buttons, labels, etc.
    Vector<String> tableColNames = new Vector<String>(1);
    Vector<String> tableRowNames = new Vector<String>(1); 
    Vector<Vector<String>> tableData = new Vector<Vector<String>>(1,1); //<row, col>

    for(int i = 0; i <50; i++){
        tableData.insertElementAt(new Vector<String>(), i);
        for(int b = 0; b<5; b++){
            tableData.elementAt(i).insertElementAt("TestData", b);
        }
        tableRowNames.insertElementAt("TestRowNames", i);
    }

    for(int a = 0; a<5; a++){
        tableColNames.insertElementAt("TestColNames", a);
    }

    System.out.println(tableData.toString());


    table = new JTable(new SemesterTableModel(tableColNames, tableRowNames, tableData));
    table.getColumnModel().getColumn(0).setCellRenderer(new JRowHeader());//Makeshift "rowHeader"
    table.setRowHeight(30);
    table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
    table.setBackground(Color.LIGHT_GRAY);



    JScrollPane scrollPane = new JScrollPane(table);
    //scrollPane.setBackground(Color.BLUE);
    springLayout.putConstraint(SpringLayout.WEST, scrollPane, 180, SpringLayout.WEST, this);
    springLayout.putConstraint(SpringLayout.NORTH, lblCumGPA, 30, SpringLayout.NORTH, scrollPane);
    springLayout.putConstraint(SpringLayout.EAST, comboBoxSemester, -15, SpringLayout.WEST, scrollPane);
    springLayout.putConstraint(SpringLayout.EAST, lblCumGPA, -15, SpringLayout.WEST, scrollPane);
    springLayout.putConstraint(SpringLayout.EAST, lblSemGPA, -15, SpringLayout.WEST, scrollPane);
    springLayout.putConstraint(SpringLayout.SOUTH, btnRemoveSemester, 0, SpringLayout.SOUTH, scrollPane);
    springLayout.putConstraint(SpringLayout.EAST, scrollPane, -15, SpringLayout.EAST, this);
    springLayout.putConstraint(SpringLayout.NORTH, scrollPane, 15, SpringLayout.NORTH, this);
    springLayout.putConstraint(SpringLayout.SOUTH, scrollPane, -15, SpringLayout.SOUTH, this);

    add(scrollPane);

    table.setFillsViewportHeight(true);

So here you see I initialize my Jtable with my SemesterTableModel and pass my 3 vectors as the parameters for my SemesterTableModel. That then passes in the below:

public class SemesterTableModel extends AbstractTableModel {

private Vector<String> colNames, rowNames;
private Vector<Vector<String>> data;

public SemesterTableModel() {
    colNames = new Vector<String>(1);
    rowNames = new Vector<String>(1);
    data = new Vector<Vector<String>>(1,1);
}

public SemesterTableModel(Vector<String> colNames, Vector<String> rowNames, Vector<Vector<String>> data){
    this.colNames = colNames;
    this.rowNames = rowNames;
    this.data = data;
}

@Override
public int getColumnCount() {
    return colNames.size();
}

@Override
public int getRowCount() {
    return rowNames.size();
}

@Override
public Object getValueAt(int col, int row) {
    if(col == 0)
        return rowNames.elementAt(row);
    else if(col >=5 || row >=5) //This is the code I added to figure out where my data was going, before I added this else if statement I was getting the array-index out of bounds errors
        return "Out of Bounds";
    else
        return data.elementAt(row).elementAt(col);
}

@Override
public boolean isCellEditable(int row, int col){
    if(col == 0 || row < 5){ //5 is an arbitrary number, I really want this to be an arbitrary variable that will be dependent on another class I haven't finished yet.
        return false;
    }
    return true;
}

}

So right now when I run my program my table looks like this.

enter image description here

Naturally I want "TestData" to fall inbetween the "row Headers" and the column Headers, "TestRowNames"to be in the first Column only, and then I also have "TestColNames" that don't even show up (though if I remember correctly I would need change the Column Header via the Jtable itself and not the TableModel).

Obviously I am not understanding something here and I have been banging my head against the keyboard for a while now trying to figure this out. If you guys know what's up or have any suggestions I am all ears.

1

1 Answers

1
votes

TableModel#getValueAt should be int row, int col not int col, int row...

public Object getValueAt(int row, int col) {

You'll have to remove the "out of bounds" check to make it work fully...because there are more then 5 rows

Take a closer look at How to Use Scroll Panes to see how you might be able to implement your own row header without needing to fake it...