如何让FlowLayout将JPanels调整到底部,就像对待其他组件一样?

Glu*_*ose 6 java layout swing layout-manager flowlayout

我有一个案例,我将JPanels添加到FlowLayout,他们没有将自己与布局的底部对齐.我正在使用它layout.setAlignOnBaseline(true),它正确地将JLabel对齐到面板的底部.但是,一旦这些标签被包裹在面板中,它就不再起作用了.这是我的意思的一个例子,顶部和底部有两个面板.

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

public class BadLayout {

    private static final Font font1 = new Font("Arial", Font.BOLD, 14);
    private static final Font font2 = new Font("Arial", Font.BOLD, 30);

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("Bad layout");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            FlowLayout layout = new FlowLayout(FlowLayout.LEADING, 0, 0);
            layout.setAlignOnBaseline(true);

            JPanel topPanel = new JPanel();
            topPanel.setLayout(layout);
            topPanel.setBackground(Color.BLACK);
            for (int i = 0; i < 10; i++) {
                JLabel label = new JLabel("Foo");
                label.setForeground(Color.WHITE);
                label.setBackground(Color.RED);
                label.setOpaque(true);
                label.setFont(i % 2 == 0 ? font1 : font2);

                JPanel subPanel = new JPanel();
                subPanel.setLayout(layout);
                subPanel.setBackground(Color.RED);
                subPanel.add(label);
                subPanel.setAlignmentY(Component.BOTTOM_ALIGNMENT);

                topPanel.add(subPanel);
            }

            JPanel bottomPanel = new JPanel();
            bottomPanel.setLayout(layout);
            bottomPanel.setBackground(Color.DARK_GRAY);
            for (int i = 0; i < 10; i++) {
                JLabel label = new JLabel("Foo");
                label.setForeground(Color.WHITE);
                label.setBackground(Color.RED);
                label.setOpaque(true);
                label.setFont(i % 2 == 0 ? font1 : font2);
                bottomPanel.add(label);
            }

            JPanel parentPanel = new JPanel();
            parentPanel.setLayout(new BorderLayout());
            parentPanel.add(topPanel, BorderLayout.NORTH);
            parentPanel.add(bottomPanel, BorderLayout.SOUTH);

            frame.getContentPane().add(parentPanel);
            frame.pack();
            frame.setVisible(true);
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您运行此代码,您会注意到顶部面板在面板中居中较小的"Foo",而底部的那个具有我希望的所需"底部对齐"行为.任何想法如何让子JPanel表现相同?

cam*_*ckr 7

setAlignOnBaseline(...)方法的API 说明:

没有基线的组件将居中

JPanel没有合理的基线可供使用,因为组件可以在多行上,具体取决于所使用的布局管理器.所以它是中心的.

我无法从您的问题中判断出您是否实际上试图将所有文本居中在基线上而与字体大小无关,或者您是否只是想在面板的底部绘制所有组件.

如果您尝试在基线上居中文本,那么您可以使用以下代码覆盖面板的基线:

JPanel subPanel = new JPanel()
{
    @Override
    public int getBaseline(int width, int height)
    {
        Component c = getComponent(0);
        return c.getBaseline(width, height);
    }
};
Run Code Online (Sandbox Code Playgroud)

当然,这仅在面板上的所有组件具有相同基线时才有效.

或者,如果您只是尝试将所有组件放在面板底部,那么您需要使用不同的布局管理器.

您可以使用相对布局将所有组件对齐到底部.

它可以用作现有代码的直接替代品:

RelativeLayout rl = new RelativeLayout(RelativeLayout.X_AXIS, 0);
rl.setAlignment( RelativeLayout.TRAILING );
JPanel topPanel = new JPanel(rl);
Run Code Online (Sandbox Code Playgroud)

或者,如果您不想使用非JDK类,则可以选择BoxLayout或者使用非JDK类GridBagLayout.

如果您使用a,BoxLayout则需要使用setAlignmentY(...)每个组件的属性.

如果使用GridBagLayout,则需要使用每个组件的约束.