vedran
vedran

Reputation: 2188

Java, how to refres JTable

I have two JTables. One is for the list of invoices and the other is for the list of products in invoices. I have created a listener so that I can get id value of invoices from first JTable with a mouse click, then using another method I generate a new table content for other table (method works fine). However, after updating table, I have tried to find ways to refresh it, unsuccessfully... I'm just looking for a way to refresh the second table the moment I trigger the mouse event

Here are parts of code:

Panel with two JTables

public JPanel tabInvoices() {

    final JPanel panel = new JPanel(new MigLayout("", "20 [grow, fill] 10 [grow, fill] 20", "20 [] 10 [] 20"));

    final DefaultTableModel model1;
    final JTable table1, table2;

    String data[][] = {};
    String col1[] = {"ID", "Date"};
    String col2[] = {"ID", "Name", "Type", "Price", "Quantity"};
    Object[][] selrowData = {};   

    /** Labels and buttons **/
    JLabel labelInv = new JLabel("List of all invoices");
    JLabel labelPro = new JLabel("List of all products in this invoice");

    /** TABLE: Invoices **/
    model1 = new DefaultTableModel(data, col1);
    invoiceInfo = new DefaultTableModel(selrowData,col2);

    /** Load the invoices from DB **/
    List<Invoice> listInv = is.getAllInvoices();
    for (int i = 0; i < listInv.size(); i++) {
        model1.insertRow(i, new Object[] {
                listInv.get(i).getID(),
                listInv.get(i).getDate()
        });
    }

    /** TABLE: Invoices **/
    table1 = new JTable(model1){
        public boolean isCellEditable(int r, int c) {
            return false;
        }
    };

    /** TABLE: Invoice Info **/
    table2 = new JTable(invoiceInfo){
        public boolean isCellEditable(int r, int c) {
            return false;
        }
    };


    /** Cell and Row selection listener **/
    ListSelectionModel cellSelectionModel = table1.getSelectionModel();
    cellSelectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    cellSelectionModel.addListSelectionListener(new ListSelectionListener() {
        @Override
        public void valueChanged(ListSelectionEvent arg0) {
            int id = (int)table1.getValueAt(row, 0);            // Get ID from first table
            invoiceInfo.getDataVector().removeAllElements();    // Remove everything from second table
            invoiceInfo = getInvoiceInfo(id, invoiceInfo);      // replace with new values

            /**
             * HERE'S WHERE I NEED TO REFRESH THE TABLE2. HOW?
             */
        }
    });


    /** Load the products from DB belonging to this invoice **/
    List<Product> listPro = is.getInvoiceInfo(row); // TODO Listener!
    for (int i = 0; i < listPro.size(); i++) {
        invoiceInfo.insertRow(i, new Object[] {
                listPro.get(i).getID(),
                listPro.get(i).getName(),
                listPro.get(i).getType(),
                listPro.get(i).getPrice(),
                listPro.get(i).getQuantity()
        });
    }
    /** Scroll Panes **/
    JScrollPane scrollInv = new JScrollPane(table1);
    JScrollPane scrollPro = new JScrollPane(table2);

    /** Add everything to the panel **/
    panel.add(labelInv);
    panel.add(labelPro, "wrap");
    panel.add(scrollInv);
    panel.add(scrollPro);

    return panel;
}

And method used to recreate the second table each time I click on any cell in left table:

public DefaultTableModel getInvoiceInfo(int id, DefaultTableModel model) {

    String data1[][] = {};
    String col1[] = {"ID", "Name", "Type", "Price", "Quantity"};
    DefaultTableModel info = new DefaultTableModel(data1,col1);

    /** Load products from DB **/
    List<Product> products = is.getInvoiceInfo(id);
    for (int i = 0; i < products.size(); i++) {
        info.insertRow(i, new Object[] {
                products.get(i).getID(),
                products.get(i).getName(),
                products.get(i).getType(),
                products.get(i).getPrice(),
                products.get(i).getQuantity()
        });
    }
    return info;
}

Upvotes: 1

Views: 513

Answers (3)

krystan honour
krystan honour

Reputation: 6793

You need to fire an event if you are modifying directly say for example via notification, methods are.

void fireTableCellUpdated(int row, int column) 
void fireTableChanged(TableModelEvent e) 
void fireTableDataChanged() 
void fireTableRowsDeleted(int firstRow, int lastRow) 
void fireTableRowsInserted(int firstRow, int lastRow)
void fireTableRowsUpdated(int firstRow, int lastRow) 
void fireTableStructureChanged() 

docs are here

If you have used something like insertRow() or addColumn() on DefaultTreeModel these events are fired for you, it depends on how you are modifying the data, if you were to later implement your own model these methods will become important, and its important you understand how they work.

It should be pointed out calling the above methods from client code outside of a custom model is bad form and a bit of a no-no they are meant to be called by the model itself.

Upvotes: 1

mKorbel
mKorbel

Reputation: 109813

1) create JTable accessible through all classes, voids or methods,

  • everywhere can get DefaultTableModel from current JTable,

  • remove rows with reverse method

code

if (myTableModel.getRowCount() > 0) {
    for (int i = myTableModel.getRowCount() - 1; i > 0; i--) {
         myTableModel.removeRow(i);
    }
}

2) wrong way as demonstrated code that you posted here by re_creating DefaulTableModel on runtime, then you have to add TableModel to the current JTable

Upvotes: 1

Adam
Adam

Reputation: 36703

No explicit code is required to refresh your table. insertRow() fires a change event for you, which the table listens to and repaints itself as necessary.

However, you're creating a new instance of DefaultTableModel in getInvoiceInfo method. This new model is not listened to by your JTable. Therefore updates via insertRow() fire changes into "thin air", and your JTable doesn't have a reference to it anyway.

A quick fix would be to change the code to the following:

public void getInvoiceInfo(int id, DefaultTableModel model) {

    /** Load products from DB **/
    List<Product> products = is.getInvoiceInfo(id);
    for (int i = 0; i < products.size(); i++) {
        model.insertRow(i, new Object[] {
                products.get(i).getID(),
                products.get(i).getName(),
                products.get(i).getType(),
                products.get(i).getPrice(),
                products.get(i).getQuantity()
        });
    }
}

Upvotes: 2

Related Questions