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

Java 使用FlowLayout的面板不能包含JScrollPanes?,java,swing,jpanel,jscrollpane,layout-manager,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(); setLocationRelati

我一开始就是这么做的

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);
    }
一切都好。但正如我之前所做的,垂直滚动条没有显示出来。这是什么原因造成的?将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

已解决: 问题在于流程布局。它环绕JScrollPane并隐藏工具栏。使用

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

答复:
JSrollPane不应在使用FlowLayout的容器中使用。

在添加面板后,必须使用
pack()
函数更新框架。当你这样做的时候

getContentPane().add(scrollPane);

功能
add
为您完成此操作()

在添加面板后,您必须使用
pack()
功能更新框架。当你这样做的时候

getContentPane().add(scrollPane);

功能
add
为您完成此操作()

在添加面板后,您必须使用
pack()
功能更新框架。当你这样做的时候

getContentPane().add(scrollPane);

功能
add
为您完成此操作()

在添加面板后,您必须使用
pack()
功能更新框架。当你这样做的时候

getContentPane().add(scrollPane);

函数
add
为您做到了这一点()

首先,使用您自己的组件作为内容窗格没有什么不好的。但默认内容窗格也是一个JPanel实例,所以实际上没有必要用您自己的面板替换它,除非您想使用非面板内容窗格或自定义面板组件

这是默认内容窗格的外观:

/**
 * 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,具有定制的布局管理器,如您所见

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

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

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

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

这是默认内容窗格的外观:

/**
 * 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,具有定制的布局管理器,如您所见

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

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

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

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

这是默认内容窗格的外观:

/**
 * 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,具有定制的布局管理器,如您所见

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

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

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

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

这是默认内容窗格的外观:

/**
 * 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,具有定制的布局管理器,如您所见

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

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

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

首先,创建第二个小组的原因是什么?那里 已经是第一个将
BoxLayout
作为布局的面板 经理台。只需设置具有第一个面板的滚动窗格 正如父母所期望的那样

你要么打电话

setContentPane(scrollPane);

现在我将解释是什么导致了这种意外行为。这 这种怪癖有时会发生在使用嵌套技术的人身上 在构建它们的布局时。使用嵌套时,布局可能会 相互影响

通过选择另一个布局--
FlowLayout
--作为基础基础布局, 您使第一个面板以其首选大小显示。相反 在一个面板中,现在有两个面板,基础面板影响 带标签的面板--它控制其大小。
FlowLayout
以首选大小显示其所有子项;它既不尊重咪咪也不尊重她 最大尺寸。因此(第一个)可见面板的大小可以显示其所有标签; 这是首选大小的计算方式——刚好足够大,可以显示其所有属性 儿童然而,有100个标签,它是非常大的;布局被破坏了。它是 垂直方向如此之大以至于我们实际上无法到达窗户的底部

因此,我们的可视面板显示所有标签,显示的目的是什么 滚动条?不需要,因为所有标签都“可见”(放置在 窗户区域),尽管设计已损坏

所以问题不在于滚动条;他们工作正常。如果你 (在您的示例中)将垂直滚动条策略设置为始终
vertical\u scrollbar\u
您将看到滚动条,但没有滑块,因为所有标签都“可见” 而且没有任何东西可以滚动。(滚动条显示隐藏在屏幕上的项目。) 布局。)问题在于
FlowLayout
仅以首选尺寸显示其组件

以下是一个按预期工作的固定代码示例:

package com.zetcode;

import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;

public class MyFrame extends JFrame {

    public MyFrame() {

        initComponents();

        setTitle("Scrollbar");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);                       
        setPreferredSize(new Dimension(300, 200));
        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_AS_NEEDED);

        setContentPane(scrollPane);
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                MyFrame ex = new MyFrame();
                ex.setVisible(true);
            }
        });
    }    
}
package com.zetcode;
导入java.awt.Dimension;
导入java.awt.EventQueue;
导入javax.swing.BoxLayout;
导入javax.swing.JFrame;
进口ja