Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jScrollPane setVisible doesn't work

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);
            }
        }
like image 305
HADEV Avatar asked Nov 21 '12 15:11

HADEV


People also ask

What happens when the method setVisible of a frame is set to false?

Later on in a program, if you call setVisible(false) the frame will become invisible, but the software object will still exist and can be made visible again with setVisible(true) .

How do I make JScrollPane transparent?

You need to use setOpaque(false) to make it transparent. Call that both on the JScrollPane, and on it's ViewPort. sp. setOpaque(false); sp.

What does setVisible mean?

setVisible(true) is a blocking operation and blocks until dialog is closed. So one dialog pops up and app blocks on setVisible(true) when you close it, another serVisible(true) is invoked and so on.


2 Answers

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

getContentPane().validate();
getContentPane().repaint();
like image 175
Dan D. Avatar answered Oct 19 '22 02:10

Dan D.


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.

like image 5
David Kroukamp Avatar answered Oct 19 '22 01:10

David Kroukamp