简体   繁体   中英

How to refresh JTable after click the JButton

I have an application which get some data from database and show it in the JTable . Everything is OK, but I want that my table will be refreshed after clicking JButton . I mean that if I write smth in JTable, after clicking JButton, application will again connect with database, get the data and show it correctly. I tried to add an ActionListener to the JButton, but I don't know what I should write in the method actionPerformed().

Here is my code:

public class App extends JFrame implements ActionListener{

protected JButton button;

public App() {

    Vector<Object> columnNames = new Vector<Object>();
    Vector<Object> data = new Vector<Object>();

    button = new JButton("Refresh");
    button.addActionListener(this);

    try
    {
    ...

    String query = "Select count(distinct country) sum from customers";
    stmt = c.createStatement();
    ResultSet rs = stmt.executeQuery(query);
    query = "SELECT * from country";
        rs = stmt.executeQuery(query);
        ResultSetMetaData md = rs.getMetaData();
        int columns = md.getColumnCount();

        for (int i = 1; i <= columns; i++)
        {
            columnNames.addElement(md.getColumnName(i));
        }

        while (rs.next())
        {
            Vector<Object> row = new Vector<Object>(columns);

            for (int i = 1; i <= columns; i++)
            {
                row.addElement(rs.getObject(i) );
            }

            data.addElement(row);
        }

        rs.close();
        stmt.close();
        c.close();
    }
    catch(Exception e)
    {
        System.out.println(e);
    }

    DefaultTableModel model = new DefaultTableModel(data, columnNames)
    {
        @Override
        public Class getColumnClass(int column)
        {
            for (int row = 0; row < getRowCount(); row++)
            {
                Object o = getValueAt(row, column);

                if (o != null)
                {
                    return o.getClass();
                }
            }

            return Object.class;
        }
    };

    JTable table = new JTable(model);
    ...
    JScrollPane scrollPane = new JScrollPane(table);
    getContentPane().add(scrollPane);

    getContentPane().add(button, BorderLayout.SOUTH);
    button.addActionListener(this);     
}

public static void main(String[] args)
{
    App frame = new App();
    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
    frame.pack();
    frame.setSize(250,300);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
}

public void actionPerformed(ActionEvent arg0) {

}
}
  1. Make the table an instance field, this way it can be accessed from the actionPerformed method
  2. Take the "data loading" part of your code and put into another method, which can be called from both your constructor and your actionPerformed method
  3. When actionPerformed is called, call the "data loading" method, create a new TableModel and apply it to the JTable

For example

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
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 java.util.Vector;
import javax.swing.JButton;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

public class App extends JFrame implements ActionListener {

    private static String dbName;
    private static String userName;
    private static String password;

    protected JButton button;

    private JTable table;

    public App() {

        button = new JButton("Refresh");
        button.addActionListener(this);

        table = new JTable();
        try {
            table.setModel(loadData());
        } catch (ClassNotFoundException | SQLException | IOException ex) {
            ex.printStackTrace();
        }

        DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
        centerRenderer.setHorizontalAlignment(JLabel.CENTER);
        table.getColumnModel().getColumn(0).setHeaderValue("Nazwa panstwa");
        table.getColumnModel().getColumn(1).setHeaderValue("Przychod netto USD");
        table.getColumnModel().getColumn(0).setCellRenderer(centerRenderer);
        table.getColumnModel().getColumn(1).setCellRenderer(centerRenderer);

        JScrollPane scrollPane = new JScrollPane(table);
        getContentPane().add(scrollPane);

        getContentPane().add(button, BorderLayout.SOUTH);
        button.addActionListener(this);
    }

    public static void main(String[] args) {
        App frame = new App();
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.pack();
        frame.setSize(250, 300);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    protected TableModel loadData() throws ClassNotFoundException, SQLException, IOException {

        Vector<Object> columnNames = new Vector<Object>();
        Vector<Object> data = new Vector<Object>();

        Class.forName("org.postgresql.Driver");

        try (Connection c = DriverManager.getConnection(dbName, userName, password)) {
            try (BufferedReader br = new BufferedReader(new FileReader("login.txt"))) {
                dbName = br.readLine();
                userName = br.readLine();
                password = br.readLine();
            }

            c.setAutoCommit(false);
            System.out.println("Opened database successfully");

            String query = "Select count(distinct country) sum from customers";

            try (Statement stmt = c.createStatement()) {
                try (ResultSet rs = stmt.executeQuery(query)) {
                    query = "SELECT C.country, SUM(O.netamount) "
                                    + "from customers as C join orders as O "
                                    + "on C.customerid = O.customerid "
                                    + "where O.orderdate < '20040701' and O.orderdate > '20031231' "
                                    + "group by C.country "
                                    + "order by SUM(O.netamount) DESC";
                    ResultSetMetaData md = rs.getMetaData();
                    int columns = md.getColumnCount();

                    for (int i = 1; i <= columns; i++) {
                        columnNames.addElement(md.getColumnName(i));
                    }

                    while (rs.next()) {
                        Vector<Object> row = new Vector<Object>(columns);

                        for (int i = 1; i <= columns; i++) {
                            row.addElement(rs.getObject(i));
                        }

                        data.addElement(row);
                    }
                }
            }
        }
        return new DefaultTableModel(data, columnNames) {
            @Override
            public Class getColumnClass(int column) {
                for (int row = 0; row < getRowCount(); row++) {
                    Object o = getValueAt(row, column);

                    if (o != null) {
                        return o.getClass();
                    }
                }

                return Object.class;
            }
        };
    }

    public void actionPerformed(ActionEvent arg0) {
        try {
            table.setModel(loadData());
        } catch (ClassNotFoundException | SQLException | IOException ex) {
            ex.printStackTrace();
        }
    }
}

You need to take better care of the resources you are creating, since Java 7, you can use try-with-resources which makes it easier to manage these types of resources

It's works, thank's. But I have one problem, when I refresh my table all data shown without format. I mean that data are not on the centre and name of the columns are default.

The reapply the formatters...

public void actionPerformed(ActionEvent arg0) {
    try {
        table.setModel(loadData());
    } catch (ClassNotFoundException | SQLException | IOException ex) {
        ex.printStackTrace();
    }
    DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
    centerRenderer.setHorizontalAlignment(JLabel.CENTER);
    table.getColumnModel().getColumn(0).setHeaderValue("Nazwa panstwa");
    table.getColumnModel().getColumn(1).setHeaderValue("Przychod netto USD");
    table.getColumnModel().getColumn(0).setCellRenderer(centerRenderer);
    table.getColumnModel().getColumn(1).setCellRenderer(centerRenderer);
}

When ever the TabelStructureChanged event is triggered, the table will reset the renderers

I haven't worked with JTable but the solution should be similar to the following.

You should move the statements that get data from the database to a separate method, let's say "getData()". Then when the button is clicked, simply call the method and create a new "DefaultTableModel" object with the newly returned data. Then call the method on your JTable reference to set the new model.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM