Java jScrollPane setVisible不';行不通

Java jScrollPane setVisible不';行不通,java,swing,jtable,jscrollpane,Java,Swing,Jtable,Jscrollpane,我有一个“显示”按钮,可以在单击时显示JTable,但该表不可见。 注意:当我删除JScrollPane时,代码正常工作,但表的标题未显示,因此请提供帮助,使此代码正常工作,而不删除JScrollPane import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.

我有一个“显示”按钮,可以在单击时显示
JTable
,但该表不可见。 注意:当我删除
JScrollPane
时,代码正常工作,但表的标题未显示,因此请提供帮助,使此代码正常工作,而不删除
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);
            }
        }

pane.setVisible之后(true)添加以下内容:

getContentPane().validate();
getContentPane().repaint();
需要注意的几点:

  • 永远不要不必要地扩展
    JFrame
    类,否则您可能需要扩展另一个类,这是非常必要的,但在java中,单个类不能扩展多个其他类(没有多重继承)

  • 始终通过
    SwingUtilities.invokeLater(Runnable r)
    block在上创建Swing组件

  • 在设置
    JFrame
    可见之前,不要使用
    setSize(..)
    调用
    JFrame#pack()

  • 不需要
    getContentPane.add(…)
    getContentPane().setLayout(…)
    ,只需在
    JFrame
    实例上调用
    add(…)
    setLayout(…)
    ,因为这些调用都是针对contentPane的

  • 您遇到的问题是,在设置“窗格可见”后,没有刷新框架/容器。我不同意@Dan。不要使用
    validate()
    getContentPane()
    也不是必需的),而是:

as
revalidate()
涵盖了
validate()
。当将新的
JComponent
s添加到可见组件时,也会使用验证,而当从可见组件中删除/添加
JComponent
时,会使用
revalidate()

下面是代码的固定版本,实现了上述功能:

按下按钮后:

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

更新:


同样,为了更可重用的
布局
,为什么不将所有组件添加到
JPanel
,并将
JPanel
添加到
JFrame
,这样,如果您需要添加更多内容,它就变得简单了。

+1对于
需要注意的几件事:
和图像输出,以及它的预期行为?为什么
pane.setVisible不可见(true)单独使用是否足够?
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();
            }
        });
    }
}