Why is nothing is displayed on JPanel?

时间:2015-07-28 16:16:27

标签: java swing jdbc jpanel

I am trying to fetch data from the database and publish the result on a JPanel.

Here is the simplified code:

public class LedgerView extends JPanel {
    public LedgerView() {
        super();

        this.setLayout(new FlowLayout());

        this.add(new JLabel("ITEMS:"));

        String JDBC_DRIVER = "com.mysql.jdbc.Driver";
        String DB_URL = "jdbc:mysql://localhost/gnufinance";
        String USERNAME = "gnufinance";
        String PASSWORD = "gnuisnotunix";
        Connection conn = null;

        try {
            Class.forName(JDBC_DRIVER);
            conn = DriverManager.getConnection(DB_URL, USERNAME, PASSWORD);
        } catch (Exception e) {
            e.printStackTrace();
        }

        String query = "SELECT * FROM transactions";
        try {
            PreparedStatement ps = conn.prepareStatement(query);
            ResultSet rs = ps.executeQuery();
            while (rs.next()) {
                String desc = rs.getString(3);
                System.out.println(desc);
                this.add(new JLabel(desc));
            }
        } catch (SQLException e) {
             e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        JFrame view = new JFrame();
        view.setVisible(true);
        view.setSize(300, 300);
        view.add(new LedgerView(), BorderLayout.CENTER);
    }

Nothing is displayed except a blank grayed frame, but when I remove the JDBC code, the first JLabel(ITEMS) is displayed. There is nothing on the screen but the System.out.println in the while loop prints all the data properly on the console. There are no exceptions.

1 个答案:

答案 0 :(得分:2)

You have to create the panel on the Event Dispatch Thread, or EDT.

Swing is not Thread Safe; any changes that you make to swing controls (such as creating new JLabels), must occur on the EDT (which is not the thread your main method starts on. You use EventQueue.invokeLater() to tell Java to move the work onto the Swing drawing thread.

Note that most of the time you do not want your work (like accessing a database) to occur on the EDT because it will make your user interface unresponsive. In other words, your program will be doing the work of accessing the database when it could, instead, be drawing your screen.

This code will fix your immediate problem, but you should consider accessing the database somewhere else (perhaps, for now, in your main method), storing the result in a List, and then passing the List to your LedgerView, which will result in a more responsive user interface.

public static void main(String[] args) {
    final JFrame view = new JFrame();

    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            view.setSize(300, 300);
            view.add(new LedgerView(), BorderLayout.CENTER);
            view.setVisible(true);
        }
    }
}