首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Java -支持水平滚动的垂直"FlowLayout“

Java -支持水平滚动的垂直"FlowLayout“
EN

Stack Overflow用户
提问于 2011-11-20 03:09:40
回答 4查看 15.9K关注 0票数 19

正如标题中所描述的,我一直在尝试建立一种带有水平滚动的垂直流布局。布局中的组件将是JLabels。让我画一张图:

代码语言:javascript
复制
+-------------------------+   <--- window
|Label1   Label4    Label7|
|Label2   Label5    Label8|   <--- labels
|Label3   Label6    Label9|
|<===============>========|   <--- scrollbar
+-------------------------+

相同的窗口,垂直扩展

代码语言:javascript
复制
+--------------------------+   <--- window
|Label1   Label5    Label9 |
|Label2   Label6    Label10|   <--- labels
|Label3   Label7    Label11|
|Label4   Label8    Label12|
|<===================>=====|   <--- scrollbar
+--------------------------+

因此,标签将填充可用的垂直空间,然后创建一个新列。一旦可用水平空间耗尽, horizontal 滚动条就会出现。

垂直滚动条通常不应该出现;但是,如果窗口的垂直高度非常小,那么有一个垂直滚动条就更好了。

任何帮助都是非常感谢的。我是Java新手,所以任何额外的解释都会很棒。谢谢!

编辑:

基于下面的回答,我现在正在使用:http://tips4java.wordpress.com/2008/11/06/wrap-layout/http://code.google.com/p/verticalflowlayout/

我让WrapLayout像这样扩展VerticalFlowLayout:

代码语言:javascript
复制
package LogicSim;

import java.awt.*;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

/**
 *  FlowLayout subclass that fully supports wrapping of components.
 */
public class VerticalWrapLayout extends VerticalFlowLayout
{
private Dimension preferredLayoutSize;

/**
* Constructs a new <code>WrapLayout</code> with a left
* alignment and a default 5-unit horizontal and vertical gap.
*/
public VerticalWrapLayout()
{
    super();
}

/**
* Constructs a new <code>FlowLayout</code> with the specified
* alignment and a default 5-unit horizontal and vertical gap.
* The value of the alignment argument must be one of
* <code>WrapLayout</code>, <code>WrapLayout</code>,
* or <code>WrapLayout</code>.
* @param align the alignment value
*/
public VerticalWrapLayout(int align)
{
    super(align);
}

/**
* Creates a new flow layout manager with the indicated alignment
* and the indicated horizontal and vertical gaps.
* <p>
* The value of the alignment argument must be one of
* <code>WrapLayout</code>, <code>WrapLayout</code>,
* or <code>WrapLayout</code>.
* @param align the alignment value
* @param hgap the horizontal gap between components
* @param vgap the vertical gap between components
*/
public VerticalWrapLayout(int align, int hgap, int vgap)
{
    super(align, hgap, vgap);
}

/**
* Returns the preferred dimensions for this layout given the
* <i>visible</i> components in the specified target container.
* @param target the component which needs to be laid out
* @return the preferred dimensions to lay out the
* subcomponents of the specified container
*/
@Override
public Dimension preferredLayoutSize(Container target)
{
    return layoutSize(target, true);
}

/**
* Returns the minimum dimensions needed to layout the <i>visible</i>
* components contained in the specified target container.
* @param target the component which needs to be laid out
* @return the minimum dimensions to lay out the
* subcomponents of the specified container
*/
@Override
public Dimension minimumLayoutSize(Container target)
{
    Dimension minimum = layoutSize(target, false);
    minimum.width -= (getHgap() + 1);
    return minimum;
}

/**
* Returns the minimum or preferred dimension needed to layout the target
* container.
*
* @param target target to get layout size for
* @param preferred should preferred size be calculated
* @return the dimension to layout the target container
*/
private Dimension layoutSize(Container target, boolean preferred)
{
        synchronized (target.getTreeLock())
        {
    //  Each row must fit with the width allocated to the containter.
    //  When the container width = 0, the preferred width of the container
    //  has not yet been calculated so lets ask for the maximum.

    int targetWidth = target.getSize().width;

    if (targetWidth == 0)
        targetWidth = Integer.MAX_VALUE;

    int hgap = getHgap();
    int vgap = getVgap();
    Insets insets = target.getInsets();
    int horizontalInsetsAndGap = insets.left + insets.right + (hgap * 2);
    int maxWidth = targetWidth - horizontalInsetsAndGap;

    //  Fit components into the allowed width

    Dimension dim = new Dimension(0, 0);
    int rowWidth = 0;
    int rowHeight = 0;

    int nmembers = target.getComponentCount();

    for (int i = 0; i < nmembers; i++)
    {
        Component m = target.getComponent(i);

        if (m.isVisible())
        {
            Dimension d = preferred ? m.getPreferredSize() : m.getMinimumSize();

            //  Can't add the component to current row. Start a new row.

            if (rowWidth + d.width > maxWidth)
            {
                addRow(dim, rowWidth, rowHeight);
                rowWidth = 0;
                rowHeight = 0;
            }

            //  Add a horizontal gap for all components after the first

            if (rowWidth != 0)
            {
                rowWidth += hgap;
            }

            rowWidth += d.width;
            rowHeight = Math.max(rowHeight, d.height);
        }
    }

    addRow(dim, rowWidth, rowHeight);

    dim.width += horizontalInsetsAndGap;
    dim.height += insets.top + insets.bottom + vgap * 2;

    //  When using a scroll pane or the DecoratedLookAndFeel we need to
    //  make sure the preferred size is less than the size of the
    //  target containter so shrinking the container size works
    //  correctly. Removing the horizontal gap is an easy way to do this.

    Container scrollPane = SwingUtilities.getAncestorOfClass(JScrollPane.class, target);

    if (scrollPane != null)
    {
        dim.width -= (hgap + 1);
    }

    return dim;
}
}

/*
 *  A new row has been completed. Use the dimensions of this row
 *  to update the preferred size for the container.
 *
 *  @param dim update the width and height when appropriate
 *  @param rowWidth the width of the row to add
 *  @param rowHeight the height of the row to add
 */
private void addRow(Dimension dim, int rowWidth, int rowHeight)
{
    dim.width = Math.max(dim.width, rowWidth);

    if (dim.height > 0)
    {
        dim.height += getVgap();
    }

    dim.height += rowHeight;
}
}

这是我的框架设置:

代码语言:javascript
复制
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(300, 300);
    frame.setVisible(true);


    JPanel panel = new JPanel();
    panel.setLayout( new VerticalWrapLayout(0) );

    JScrollPane pane = new JScrollPane(panel);
    frame.add( pane, BorderLayout.CENTER );

    for (int i=0; i < 80; i++ ) {
        panel.add( new JLabel( "Label" + i ) );
    }

现在,这将按照我想要的方式在垂直列中设置标签,但它仍然会创建垂直滚动条。当涉及到修改VerticalWrapLayout类时,我非常不确定。另外,我真的不明白JScrollPane如何与这些类交互。对如何进行有什么建议吗?

解决了!请看下面的答案和我的答案。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-11-20 13:07:05

下面是一个VerticalFlowLayout的示例。它是FlowLayout类的副本,将一些逻辑更改为“垂直”方向,而不是“水平”方向:

代码语言:javascript
复制
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

/**
 * A flow layout arranges components in a directional flow, much
 * like lines of text in a paragraph. The flow direction is
 * determined by the container's <code>componentOrientation</code>
 * property and may be one of two values:
 * <ul>
 * <li><code>ComponentOrientation.TOP_TO_BOTTOM</code>
 * <li><code>ComponentOrientation.BOTTOM_TO_TOP</code>
 * </ul>
 * Flow layouts are typically used
 * to arrange buttons in a panel. It arranges buttons
 * horizontally until no more buttons fit on the same line.
 * The line alignment is determined by the <code>align</code>
 * property. The possible values are:
 * <ul>
 * <li>{@link #TOP TOP}
 * <li>{@link #BOTTOM BOTTOM}
 * <li>{@link #CENTER CENTER}
 * <li>{@link #LEADING LEADING}
 * <li>{@link #TRAILING TRAILING}
 * </ul>
 * <p>
 */
public class VerticalFlowLayout implements LayoutManager, java.io.Serializable
{
    /**
     * This value indicates that each row of components
     * should be left-justified.
     */
    public static final int TOP     = 0;

    /**
     * This value indicates that each row of components
     * should be centered.
     */
    public static final int CENTER    = 1;

    /**
     * This value indicates that each row of components
     * should be right-justified.
     */
    public static final int BOTTOM     = 2;

    /**
     * <code>align</code> is the property that determines
     * how each column distributes empty space.
     * It can be one of the following three values:
     * <ul>
     * <code>TOP</code>
     * <code>BOTTOM</code>
     * <code>CENTER</code>
     * </ul>
     *
     * @see #getAlignment
     * @see #setAlignment
     */
    int align;     // This is the one we actually use

    /**
     * The flow layout manager allows a seperation of
     * components with gaps.  The horizontal gap will
     * specify the space between components and between
     * the components and the borders of the
     * <code>Container</code>.
     *
     * @see #getHgap()
     * @see #setHgap(int)
     */
    int hgap;

    /**
     * The flow layout manager allows a seperation of
     * components with gaps.  The vertical gap will
     * specify the space between rows and between the
     * the rows and the borders of the <code>Container</code>.
     *
     * @see #getHgap()
     * @see #setHgap(int)
     */
    int vgap;

    /**
     * Constructs a new <code>VerticalFlowLayout</code> with a centered alignment and a
     * default 5-unit horizontal and vertical gap.
     */
    public VerticalFlowLayout()
    {
        this(CENTER, 5, 5);
    }

    /**
     * Constructs a new <code>VerticalFlowLayout</code> with the specified
     * alignment and a default 5-unit horizontal and vertical gap.
     * The value of the alignment argument must be one of
     * <code>VerticalFlowLayout.TOP</code>, <code>VerticalFlowLayout.BOTTOM</code>,
     * or <code>VerticalFlowLayout.CENTER</code>
     * @param align the alignment value
     */
    public VerticalFlowLayout(int align)
    {
        this(align, 5, 5);
    }

    /**
     * Creates a new flow layout manager with the indicated alignment
     * and the indicated horizontal and vertical gaps.
     * <p>
     * The value of the alignment argument must be one of
     * <code>VerticalFlowLayout.TOP</code>, <code>VerticalFlowLayout.BOTTOM</code>,
     * or <code>VerticalFlowLayout.CENTER</code>.
     * @param     align   the alignment value
     * @param     hgap  the horizontal gap between components
     *                   and between the components and the
     *                   borders of the <code>Container</code>
     * @param     vgap  the vertical gap between components
     *                   and between the components and the
     *                   borders of the <code>Container</code>
     */
    public VerticalFlowLayout(int align, int hgap, int vgap)
    {
        this.hgap = hgap;
        this.vgap = vgap;
        setAlignment(align);
    }

    /**
     * Gets the alignment for this layout.
     * Possible values are <code>VerticalFlowLayout.TOP</code>,
     * <code>VerticalFlowLayout.BOTTOM</code> or <code>VerticalFlowLayout.CENTER</code>,
     * @return   the alignment value for this layout
     * @see     java.awt.VerticalFlowLayout#setAlignment
     * @since     JDK1.1
     */
    public int getAlignment()
    {
        return align;
    }

    /**
     * Sets the alignment for this layout. Possible values are
     * <ul>
     * <li><code>VerticalFlowLayout.TOP</code>
     * <li><code>VerticalFlowLayout.BOTTOM</code>
     * <li><code>VerticalFlowLayout.CENTER</code>
     * </ul>
     * @param     align one of the alignment values shown above
     * @see     #getAlignment()
     * @since     JDK1.1
     */
    public void setAlignment(int align)
    {
        this.align = align;
    }

    /**
     * Gets the horizontal gap between components
     * and between the components and the borders
     * of the <code>Container</code>
     *
     * @return   the horizontal gap between components
     *           and between the components and the borders
     *           of the <code>Container</code>
     * @see     java.awt.VerticalFlowLayout#setHgap
     * @since     JDK1.1
     */
    public int getHgap() {
        return hgap;
    }

    /**
     * Sets the horizontal gap between components and
     * between the components and the borders of the
     * <code>Container</code>.
     *
     * @param hgap the horizontal gap between components
     *           and between the components and the borders
     *           of the <code>Container</code>
     * @see     java.awt.VerticalFlowLayout#getHgap
     * @since     JDK1.1
     */
    public void setHgap(int hgap) {
        this.hgap = hgap;
    }

    /**
     * Gets the vertical gap between components and
     * between the components and the borders of the
     * <code>Container</code>.
     *
     * @return   the vertical gap between components
     *           and between the components and the borders
     *           of the <code>Container</code>
     * @see     java.awt.VerticalFlowLayout#setVgap
     * @since     JDK1.1
     */
    public int getVgap() {
        return vgap;
    }

    /**
     * Sets the vertical gap between components and between
     * the components and the borders of the <code>Container</code>.
     *
     * @param vgap the vertical gap between components
     *           and between the components and the borders
     *           of the <code>Container</code>
     * @see     java.awt.VerticalFlowLayout#getVgap
     */
    public void setVgap(int vgap) {
        this.vgap = vgap;
    }

    /**
     * Adds the specified component to the layout.
     * Not used by this class.
     * @param name the name of the component
     * @param comp the component to be added
     */
    public void addLayoutComponent(String name, Component comp) {
    }

    /**
     * Removes the specified component from the layout.
     * Not used by this class.
     * @param comp the component to remove
     * @see    java.awt.Container#removeAll
     */
    public void removeLayoutComponent(Component comp) {
    }

    /**
     * Returns the preferred dimensions for this layout given the
     * <i>visible</i> components in the specified target container.
     *
     * @param target the container that needs to be laid out
     * @return  the preferred dimensions to lay out the
     *          subcomponents of the specified container
     * @see Container
     * @see #minimumLayoutSize
     * @see    java.awt.Container#getPreferredSize
     */
    public Dimension preferredLayoutSize(Container target)
    {
    synchronized (target.getTreeLock())
    {
        Dimension dim = new Dimension(0, 0);
        int nmembers = target.getComponentCount();
        boolean firstVisibleComponent = true;

        for (int i = 0 ; i < nmembers ; i++)
        {
            Component m = target.getComponent(i);

            if (m.isVisible())
            {
                Dimension d = m.getPreferredSize();
                dim.width = Math.max(dim.width, d.width);

                if (firstVisibleComponent)
                {
                    firstVisibleComponent = false;
                }
                else
                {
                    dim.height += vgap;
                }

                dim.height += d.height;
            }
        }

        Insets insets = target.getInsets();
        dim.width += insets.left + insets.right + hgap*2;
        dim.height += insets.top + insets.bottom + vgap*2;
        return dim;
    }
    }

    /**
     * Returns the minimum dimensions needed to layout the <i>visible</i>
     * components contained in the specified target container.
     * @param target the container that needs to be laid out
     * @return  the minimum dimensions to lay out the
     *          subcomponents of the specified container
     * @see #preferredLayoutSize
     * @see    java.awt.Container
     * @see    java.awt.Container#doLayout
     */
    public Dimension minimumLayoutSize(Container target)
    {
    synchronized (target.getTreeLock())
    {
        Dimension dim = new Dimension(0, 0);
        int nmembers = target.getComponentCount();
        boolean firstVisibleComponent = true;

        for (int i = 0 ; i < nmembers ; i++)
        {
            Component m = target.getComponent(i);
            if (m.isVisible())
            {
                Dimension d = m.getMinimumSize();
                dim.width = Math.max(dim.width, d.width);

                if (firstVisibleComponent)
                {
                    firstVisibleComponent = false;
                }
                else
                {
                    dim.height += vgap;
                }

                dim.height += d.height;
            }
        }


        Insets insets = target.getInsets();
        dim.width += insets.left + insets.right + hgap*2;
        dim.height += insets.top + insets.bottom + vgap*2;
        return dim;
    }
    }

    /**
     * Lays out the container. This method lets each
     * <i>visible</i> component take
     * its preferred size by reshaping the components in the
     * target container in order to satisfy the alignment of
     * this <code>VerticalFlowLayout</code> object.
     *
     * @param target the specified component being laid out
     * @see Container
     * @see    java.awt.Container#doLayout
     */
    public void layoutContainer(Container target)
    {
    synchronized (target.getTreeLock())
    {
        Insets insets = target.getInsets();
        int maxHeight = target.getSize().height - (insets.top + insets.bottom + vgap*2);
        int nmembers = target.getComponentCount();
        int x = insets.left + hgap;
        int y = 0;
        int columnWidth = 0;
        int start = 0;

        boolean ttb = target.getComponentOrientation().isLeftToRight();

        for (int i = 0 ; i < nmembers ; i++)
        {
            Component m = target.getComponent(i);

            if (m.isVisible())
            {
                Dimension d = m.getPreferredSize();
                m.setSize(d.width, d.height);

                if ((y == 0) || ((y + d.height) <= maxHeight))
                {
                    if (y > 0)
                    {
                        y += vgap;
                    }

                    y += d.height;
                    columnWidth = Math.max(columnWidth, d.width);
                }
                else
                {
                    moveComponents(target, x, insets.top + vgap, columnWidth, maxHeight - y, start, i, ttb);
                    y = d.height;
                    x += hgap + columnWidth;
                    columnWidth = d.width;
                    start = i;
                }
            }
        }

        moveComponents(target, x, insets.top + vgap, columnWidth, maxHeight - y, start, nmembers, ttb);
    }
    }

    /**
     * Centers the elements in the specified row, if there is any slack.
     * @param target the component which needs to be moved
     * @param x the x coordinate
     * @param y the y coordinate
     * @param width the width dimensions
     * @param height the height dimensions
     * @param columnStart the beginning of the column
     * @param columnEnd the the ending of the column
     */
    private void moveComponents(
        Container target, int x, int y, int width, int height, int columnStart, int columnEnd, boolean ttb)
    {
        switch (align)
        {
            case TOP:
                y += ttb ? 0 : height;
                break;
            case CENTER:
                y += height / 2;
                break;
            case BOTTOM:
                y += ttb ? height : 0;
                break;
        }

        for (int i = columnStart ; i < columnEnd ; i++)
        {
            Component m = target.getComponent(i);

            if (m.isVisible())
            {
                int cx;
                cx = x + (width - m.getSize().width) / 2;

                if (ttb)
                {
                    m.setLocation(cx, y);
                }
                else
                {
                    m.setLocation(cx, target.getSize().height - y - m.getSize().height);
                }

                y += m.getSize().height + vgap;
            }
        }
    }

    /**
     * Returns a string representation of this <code>VerticalFlowLayout</code>
     * object and its values.
     * @return   a string representation of this layout
     */
    public String toString()
    {
        String str = "";

        switch (align)
        {
            case TOP:    str = ",align=top"; break;
            case CENTER: str = ",align=center"; break;
            case BOTTOM: str = ",align=bottom"; break;
        }

        return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + str + "]";
    }


    public static void main(String[] args)
    {
        JPanel main = new JPanel( new BorderLayout() );

        final JPanel buttons = new JPanel(new VerticalFlowLayout() );
//      buttons.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
        main.add(buttons, BorderLayout.CENTER);

        for (int i = 0; i < 7; i++)
        {
            buttons.add( new JRadioButton("button " + i) );
        }

        JButton button = new JButton("Add Radio Button");
        main.add(button, BorderLayout.SOUTH);
        button.addActionListener( new ActionListener()
        {
            private int i = 8;

            public void actionPerformed(ActionEvent e)
            {
                buttons.add( new JRadioButton("button R Us" + i++) );
                buttons.revalidate();
//              pack();
            }
        });

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(main);
        frame.setSize(300, 300);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }


}

从理论上讲,您应该能够使用WrapLayout并让它扩展这个类,然后定制代码,使其也是垂直定向的。

编辑:

我让WrapLayout这样扩展VerticalFlowLayout:

您不能简单地扩展VerticalFlowLayout。WrapLayout代码旨在根据父容器的大小计算固定宽度。您需要更改计算固定高度的行为。我没有尝试过,但基本上你需要将"width“相关变量的引用更改为"height”,将"height“相关的变量引用更改为"width”,这样代码就可以在垂直维度而不是水平维度上工作。

票数 16
EN

Stack Overflow用户

发布于 2011-11-20 23:39:37

这是我使用的修改后的VerticalWrapLayout,如果有人感兴趣的话!

代码语言:javascript
复制
package LogicSim;

import java.awt.*;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

/**
 *  FlowLayout subclass that fully supports wrapping of components.
 */
public class VerticalWrapLayout extends VerticalFlowLayout
{
private Dimension preferredLayoutSize;

/**
* Constructs a new <code>WrapLayout</code> with a left
* alignment and a default 5-unit horizontal and vertical gap.
*/
public VerticalWrapLayout()
{
    super();
}

/**
* Constructs a new <code>FlowLayout</code> with the specified
* alignment and a default 5-unit horizontal and vertical gap.
* The value of the alignment argument must be one of
* <code>WrapLayout</code>, <code>WrapLayout</code>,
* or <code>WrapLayout</code>.
* @param align the alignment value
*/
public VerticalWrapLayout(int align)
{
    super(align);
}

/**
* Creates a new flow layout manager with the indicated alignment
* and the indicated horizontal and vertical gaps.
* <p>
* The value of the alignment argument must be one of
* <code>WrapLayout</code>, <code>WrapLayout</code>,
* or <code>WrapLayout</code>.
* @param align the alignment value
* @param hgap the horizontal gap between components
* @param vgap the vertical gap between components
*/
public VerticalWrapLayout(int align, int hgap, int vgap)
{
    super(align, hgap, vgap);
}

/**
* Returns the preferred dimensions for this layout given the
* <i>visible</i> components in the specified target container.
* @param target the component which needs to be laid out
* @return the preferred dimensions to lay out the
* subcomponents of the specified container
*/
@Override
public Dimension preferredLayoutSize(Container target)
{
    return layoutSize(target, true);
}

/**
* Returns the minimum dimensions needed to layout the <i>visible</i>
* components contained in the specified target container.
* @param target the component which needs to be laid out
* @return the minimum dimensions to lay out the
* subcomponents of the specified container
*/
@Override
public Dimension minimumLayoutSize(Container target)
{
    Dimension minimum = layoutSize(target, false);
    minimum.height -= (getVgap() + 1);
    return minimum;
}

/**
* Returns the minimum or preferred dimension needed to layout the target
* container.
*
* @param target target to get layout size for
* @param preferred should preferred size be calculated
* @return the dimension to layout the target container
*/
private Dimension layoutSize(Container target, boolean preferred)
{
        synchronized (target.getTreeLock())
        {
    //  Each row must fit with the width allocated to the containter.
    //  When the container width = 0, the preferred width of the container
    //  has not yet been calculated so lets ask for the maximum.

    int targetHeight = target.getSize().height;

    if (targetHeight == 0)
        targetHeight = Integer.MAX_VALUE;

    int hgap = getHgap();
    int vgap = getVgap();
    Insets insets = target.getInsets();
    int verticalInsetsAndGap = insets.top + insets.bottom + (vgap * 2);
    int maxHeight = targetHeight - verticalInsetsAndGap;

    //  Fit components into the allowed height

    Dimension dim = new Dimension(0, 0);
    int rowWidth = 0;
    int rowHeight = 0;

    int nmembers = target.getComponentCount();

    for (int i = 0; i < nmembers; i++)
    {
        Component m = target.getComponent(i);

        if (m.isVisible())
        {
            Dimension d = preferred ? m.getPreferredSize() : m.getMinimumSize();

            //  Can't add the component to current row. Start a new row.

            if (rowHeight + d.height > maxHeight)
            {
                addColumn(dim, rowWidth, rowHeight);
                rowWidth = 0;
                rowHeight = 0;
            }

            //  Add a horizontal gap for all components after the first

            if (rowHeight != 0)
            {
                rowHeight += vgap;
            }

                            // ******************************************************
            rowHeight += d.height;
                            rowWidth = Math.max(rowWidth, d.width);
        }
    }

    addColumn(dim, rowWidth, rowHeight);

    dim.height += verticalInsetsAndGap;
    dim.width += insets.left + insets.right + hgap * 2;

    //When using a scroll pane or the DecoratedLookAndFeel we need to
    //  make sure the preferred size is less than the size of the
    //  target containter so shrinking the container size works
    //  correctly. Removing the horizontal gap is an easy way to do this.

    Container scrollPane = SwingUtilities.getAncestorOfClass(JScrollPane.class, target);

    if (scrollPane != null)
    {
        dim.height -= (vgap + 1);
    }

    return dim;
}
}

/*
 *  A new row has been completed. Use the dimensions of this row
 *  to update the preferred size for the container.
 *
 *  @param dim update the width and height when appropriate
 *  @param rowWidth the width of the row to add
 *  @param rowHeight the height of the row to add
 */
private void addColumn(Dimension dim, int rowWidth, int rowHeight)
{
    dim.height = Math.max(dim.height, rowHeight);

    if (dim.width > 0)
    {
        dim.width += getHgap();
    }

    dim.width += rowWidth;
}
}

谢谢大家!

票数 10
EN

Stack Overflow用户

发布于 2011-11-20 03:49:10

您可以使用BoxLayout

例如:

代码语言:javascript
复制
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

public class CustomFrame extends JFrame
{

    private int labelCounter = 0;
    private int maxLabels = 3;
    private Box box;
    private JPanel pane;

    public CustomFrame()
    {
        super("Custom JFrame");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pane = new JPanel();
        pane.setLayout(new BoxLayout(pane, BoxLayout.X_AXIS));
        JScrollPane scr = new JScrollPane(pane);
        add(scr);

        for(int i = 1; i <= 15; i++) addNewLabel("Label " + i);

        setSize(200,130);
        setVisible(true);
    }

    private void addNewLabel(String s)
    {
        if(labelCounter % maxLabels == 0)
        {
            box = Box.createVerticalBox();
            box.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
        }
        box.add(new JLabel(s));
        pane.add(box);
        labelCounter++;
    }

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

    }
}
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8196530

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档