6

I have a show button to show a JTable on click but the table is not visible. Note: when I remove the JScrollPane the code works properly but the header of the table is not shown, so any help please to make this code work properly without removing the JScrollPane

        import java.awt.event.ActionEvent;
        import java.awt.event.ActionListener;

        import javax.swing.JButton;
        import javax.swing.JFrame;
        import javax.swing.JScrollPane;
        import javax.swing.JTable;
        import javax.swing.table.DefaultTableModel;

        public class Training extends JFrame {

            public Training() {

                getContentPane().setLayout(new FlowLayout());
                JTable table = new JTable();
                table.setModel(new DefaultTableModel(new Object[][] { { "joe", "joe" },
                        { "mickel", "mickel" }, }, new String[] { "LastName",
                        "FirstName" }));
                final JScrollPane pane = new JScrollPane(table);
                pane.setVisible(false);
                getContentPane().add(pane);

                JButton btn = new JButton("show");
                add(btn);
                btn.addActionListener(new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        // TODO Auto-generated method stub
                        pane.setVisible(true);
                    }
                });
            }

            public static void main(String[] args) {
                Training app = new Training();
                app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                app.setSize(600, 600);
                app.setVisible(true);
            }
        }
messivanio
  • 2,263
  • 18
  • 24
HADEV
  • 437
  • 8
  • 19

2 Answers2

8

After pane.setVisible(true); add the following:

getContentPane().validate();
getContentPane().repaint();
Dan D.
  • 32,246
  • 5
  • 63
  • 79
5

A few things to note:

  • Never extends JFrame class unnecessarily, or else you might need to extend another class which is very necessary but in java a single class may not extend more than one other class (no multiple inheritance).

  • Always create Swing components on Event Dispatch Thread via SwingUtilities.invokeLater(Runnable r) block.

  • Do not use setSize(..) call JFrame#pack() before setting JFrame visible

  • No need for getContentPane.add(..) or getContentPane().setLayout(..), simply call add(..) or setLayout(..) on JFrame instance as these calls are fowared to the contentPane.

  • The problem you have is you do not refresh you frame/container after setting pane visible. I disagree with @Dan. Do not use validate() (getContentPane() is not necesarry either) rather:

    revalidate();
    repaint();
    

as revalidate() covers validate(). Also validate is used when new JComponents are added to a visible component, whereas revalidate() is used when JComponent is removed/added from a visible component.

Here is a fixed version of the code with the above implemented:

enter image description here

After button pressed:

enter image description here

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;

public class Training {

    private JFrame frame;

    public Training() {
        frame = new JFrame();
        frame.setLayout(new FlowLayout());
        JTable table = new JTable();
        table.setModel(new DefaultTableModel(new Object[][]{{"joe", "joe"},
                    {"mickel", "mickel"},}, new String[]{"LastName",
                    "FirstName"}));
        final JScrollPane pane = new JScrollPane(table);
        pane.setVisible(false);
        frame.add(pane);

        JButton btn = new JButton("show");
        frame.add(btn);

        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                pane.setVisible(true);

                frame.pack();//this is so the frame will resize after adding pane
                frame.revalidate();
                frame.repaint();
            }
        });

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Training();
            }
        });
    }
}

UPDATE:

Also for a more reusable Layout, why not add all components to a JPanel, and add that JPanel to the JFrame, thus if you ever need to add more stuff its simple.

David Kroukamp
  • 36,155
  • 13
  • 81
  • 138