Java,如何刷新JTable

时间:2012-03-20 16:29:45

标签: java swing jtable actionlistener repaint

我对GUI很新,所以请和我一起玩。无论如何,我有两个JTable。一个是发票清单,另一个是发票中的产品清单。我创建了一个监听器,以便我可以通过鼠标单击从第一个JTable获取发票的id值,然后使用另一个方法我为其他表生成一个新的表内容(方法工作正常)。但是,在更新表之后,我试图找到刷新它的方法,但是没有成功...我只是在寻找一种方法来在我触发鼠标事件时刷新第二个表

以下是代码的一部分:

具有两个JTable的面板

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;
}

每次单击左表中的任何单元格时,用于重新创建第二个表的方法:

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;
}

3 个答案:

答案 0 :(得分:2)

刷新表格不需要显式代码。 insertRow()为您触发一个change事件,表会监听并根据需要自行重新绘制。

但是,您正在getInvoiceInfo方法中创建DefaultTableModel的新实例。 JTable不会监听这个新模型。因此,通过insertRow()更新的更新变为“稀薄空气”,并且您的JTable无论如何都没有引用它。

快速解决方法是将代码更改为以下内容:

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()
        });
    }
}

答案 1 :(得分:1)

如果要直接修改,则需要触发事件,例如通过通知,方法是。

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

如果您在 DefaultTreeModel 上使用了类似 insertRow() addColumn()的内容,则会为您触发这些事件,具体取决于具体方式你正在修改数据,如果你以后实现自己的模型,这些方法将变得很重要,重要的是你了解它们是如何工作的。

应该指出的是,从自定义模型之外的客户端代码调用上述方法是不好的形式,而且一些禁止它们是由模型本身调用的。

答案 2 :(得分:1)

1)通过所有类别,空白或方法创建JTable

  • 到处都可以从当前DefaultTableModel获取JTable

  • 使用反向方法删除行

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

2)通过在运行时重新创建DefaulTableModel而在此处发布的演示代码的错误方式,然后您必须将TableModel添加到当前JTable