我怎么能让FlowLayout在底部对齐jpanel,就像它对其他组件一样



我有一个情况,我正在添加jpanel到FlowLayout,他们没有对齐到布局的底部。我使用这个layout.setAlignOnBaseline(true),它正确地将JLabels对齐到面板的底部。然而,一旦这些标签被包裹在面板中,它就不再起作用了。这里有一个例子,上面和下面有两个面板。

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

如果你运行这段代码,你会注意到顶部的面板有较小的"Foo"在面板的中心,而底部的面板有我希望的"底部对齐"行为。任何想法如何让子jpanel的行为相同?

setAlignOnBaseline(...)方法的API状态:

没有基线的组件将居中

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

从你的问题中,我看不出你是真的想把所有的文本都放在基线的中心,不受字体大小的影响,还是只是想让所有的组件都画在面板的底部。

如果你想让文本居中,那么你可以用下面的代码覆盖面板的基线:

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

当然,只有当面板上的所有组件具有相同的基线时,这才会起作用。

或者如果你只是想把所有的组件都放在面板的底部,那么你需要使用一个不同的布局管理器。

你可以使用相对布局来对齐所有的组件到底部。

它可以直接替换你现有的代码:

RelativeLayout rl = new RelativeLayout(RelativeLayout.X_AXIS, 0);
rl.setAlignment( RelativeLayout.TRAILING );
JPanel topPanel = new JPanel(rl);

或者如果您不想使用非JDK类,那么BoxLayoutGridBagLayout将是您的选择。

如果你使用BoxLayout,那么你需要使用每个组件的setAlignmentY(...)属性。

如果您使用GridBagLayout,那么您将需要使用每个组件的约束。

我自己,我会使用比FlowLayout更有"魅力"的布局,比如GridBagLayout。如果你使用它,你可以设置锚为SOUTH,重量为0.0,这应该防止组件拉伸其高度,并将其放置在底部。例如:

   JPanel topPanel = new JPanel();
    // topPanel.setLayout(layout);
    topPanel.setLayout(new GridBagLayout());
    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);
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = i;
        gbc.gridy = 0;
        gbc.weightx = 1.0;
        gbc.weighty = 0.0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.anchor = GridBagConstraints.SOUTH;
        JPanel subPanel = new JPanel();
        subPanel.setLayout(new BorderLayout());
        subPanel.setBackground(Color.RED);
        subPanel.add(label);
        subPanel.setPreferredSize(subPanel.getMinimumSize());
        // subPanel.setAlignmentY(Component.BOTTOM_ALIGNMENT);   
        topPanel.add(subPanel, gbc);
    }

在考虑了如何在没有griddbaglayout的情况下做到这一点之后,我想到了这个,尽管它有点"hackish":

        JPanel topPanel = new JPanel();
        ((FlowLayout) topPanel.getLayout()).setAlignOnBaseline(true);
        topPanel.setBackground(Color.BLACK);
        int h = 0;
        for (int i = 0; i < 10; i++) {
            JLabel label = new JLabel("Foo");
            label.setForeground(Color.WHITE);
            label.setBackground(Color.GREEN);
            label.setOpaque(true);
            label.setFont(i % 2 == 0 ? font1 : font2);
            JPanel wrapBorder = new JPanel(new BorderLayout());
            JPanel subPanel = new JPanel();
            subPanel.setBackground(Color.RED);
            subPanel.add(label);
            subPanel.setBackground(Color.GREEN);
            wrapBorder.setOpaque(false);
            wrapBorder.add(BorderLayout.SOUTH, subPanel);
            if(wrapBorder.getPreferredSize().height > h) {
                h = wrapBorder.getPreferredSize().height;
            }
            topPanel.add(wrapBorder);
        }
        for(Component component : topPanel.getComponents()) {
            component.setPreferredSize(new Dimension(component.getPreferredSize().width, h));
        }

我这样做的唯一原因是我个人从来没有使用过GridBagLayout,但它有它的优点(可以看出;))。

我可能只是错过了一个方法,使JPanel的垂直扩展,我过于复杂的东西很多。

相关内容

  • 没有找到相关文章

最新更新