java - 使用 FlowLayout 的面板不能包含 JScrollPanes?

标签 java swing jpanel jscrollpane layout-manager

我一开始就是这么做的。

public class MyFrame extends JFrame {

    public MyFrame() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setPreferredSize(new Dimension(500 ,300));
        setResizable(false);
        pack();
        setLocationRelativeTo(null);

        initComponents();
    }

    private void initComponents() {

        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

        for (int i=0; i < 100; i++)
            panel.add(new JLabel("some text"));

        JScrollPane scrollPane = new JScrollPane(panel, 
                ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, 
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

        // Here I create a JPanel to replace the contentPane of JFrame
        JPanel contentPane = new JPanel();
        contentPane.add(scrollPane);
        setContentPane(contentPane);
    }

如果我用以下内容替换最后 3 行:

getContentPane().add(scrollPane);   

一切都好。但正如我之前所做的那样,垂直滚动条没有显示。是什么原因造成的?将 JPanel 设置为 contentPane 是否错误?

更新: 如果 contentPane 更改为 BorderLayout 一切正常。

// Here I create a JPanel to replace the contentPane of JFrame
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.add(scrollPane);
setContentPane(contentPane);

所以问题出在默认的 FlowLayout 上?

已解决: 问题出在 FlowLayout 上。它环绕 JScrollPane 并隐藏工具栏。使用

scrollPane.setPreferredSize(new Dimension(500, 400)); // longer space in x-axis

解决了。

答案: JSrollPane 不应在使用 FlowLayout 的容器内使用。

最佳答案

首先 - 使用您自己的组件作为内容 Pane 并没有什么不好。但默认内容 Pane 也是一个 JPanel 实例,因此实际上没有必要将其替换为您自己的面板,除非您想使用非面板内容 Pane 或自定义面板组件。

默认内容 Pane 如下所示:

/**
 * Called by the constructor methods to create the default 
 * <code>contentPane</code>. 
 * By default this method creates a new <code>JComponent</code> add sets a 
 * <code>BorderLayout</code> as its <code>LayoutManager</code>.
 * @return the default <code>contentPane</code>
 */
protected Container createContentPane() {
    JComponent c = new JPanel();
    c.setName(this.getName()+".contentPane");
    c.setLayout(new BorderLayout() {
        /* This BorderLayout subclass maps a null constraint to CENTER.
         * Although the reference BorderLayout also does this, some VMs
         * throw an IllegalArgumentException.
         */
        public void addLayoutComponent(Component comp, Object constraints) {
            if (constraints == null) {
                constraints = BorderLayout.CENTER;
            }
            super.addLayoutComponent(comp, constraints);
        }
    });
    return c;
}

该方法取自JRootPane。正如您所看到的,它基本上是一个简单的 JPanel,带有一个自定义的布局管理器。

现在,您的示例中存在一些问题。

首先是调用的顺序 - 您在向框架添加内容之前调整框架的大小。只需更改顺序,您就会看到滚动 Pane :

public class MyFrame extends JFrame
{
    public MyFrame ()
    {
        super();

        // Add components first
        initComponents ();

        // Setup frame after so it fits its new content
        setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
        setPreferredSize ( new Dimension ( 500, 300 ) );
        setResizable ( false );
        pack ();
        setLocationRelativeTo ( null );
    }

    private void initComponents ()
    {
        JPanel panel = new JPanel ();
        panel.setLayout ( new BoxLayout ( panel, BoxLayout.Y_AXIS ) );

        for ( int i = 0; i < 100; i++ )
        {
            panel.add ( new JLabel ( "some text" ) );
        }

        JScrollPane scrollPane =
                new JScrollPane ( panel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER );

        // Here I create a JPanel to replace the contentPane of JFrame
        JPanel contentPane = new JPanel ();
        contentPane.add ( scrollPane );
        setContentPane ( contentPane );
    }

    public static void main ( String[] args )
    {
        SwingUtilities.invokeLater ( new Runnable ()
        {
            public void run ()
            {
                new MyFrame ().setVisible ( true );
            }
        } );
    }
}

它看起来仍然会有所不同,因为您的 new JPanel () 默认情况下使用 FlowLayout,而不是默认内容 Pane 组件使用的 BorderLayout:
With FlowLayout

只需设置BorderLayout,您就会得到您想要看到的结果:

JPanel contentPane = new JPanel ( new BorderLayout () );

关于java - 使用 FlowLayout 的面板不能包含 JScrollPanes?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24698143/

相关文章:

java - 声学模型路径未设置正确 CMU Sphinx

java - 在 MariaDB 上使用 Hibernate 进行 JPQL 更新查询时出错

java - 在同一 JTable 单元格中渲染多个对象

java - JPanel 缩放时不显示背景图片

java - 如何在java中捕获全局按键

java - Eclipse 项目 - 以编程方式添加链接资源

Java面向对象编程策略

java - Java中用计算结果的值替换JTable的值

java - 给 JPanel 一个基于百分比的宽度

java - 如何动态更改 JFrame 内的 JPanel?