使用 BoxLayout 布局管理器自动高度

Automatic height using BoxLayout Layout Manager

我有一个新问题,在抓挠解决方案时,我的头发一直伸到头骨。 我在下面模拟了我的问题,(我不知道这是否是正常程序,但我倾向于简化以理解问题并尝试修复它)。 我需要有一个分为 70/30% 部分的两列 JPanel。 用户将在这些单独的列中添加大量的 JLabel 和 JTextFields 等,所有宽度都不同。我不能使用 GridLayout,因为并非所有对象的宽度都相同。当用户插入太多对象时,我希望整个 JPanel 滚动。到目前为止,我已经实现了 3 个 JPanel,其中一个主要是 BoxLayout,其中有 2 个 FlowLayout JPanel,在每个子 JPanel 中我都添加了我的对象。问题是我希望将 JScrollPane 应用于 MainPanel,而不是单独应用于每个子 JPanel,否则它会很难看。我不知道如何以 JScroll 应用于我的整个 MainPanel 的方式将 setSize 仅设置为宽度而不是高度。 谢谢并致以最诚挚的问候

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Toolkit;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class alignments {

    Toolkit toolkit;
    JFrame frame;
    JPanel mainPanel, leftPanel, rightPanel;

    public static void main(String[] args) {
        alignments align = new alignments();
    }

    alignments() {
        frame = new JFrame();
        setDimm();

        mainPanel = new JPanel();
        leftPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5));
        rightPanel = new JPanel();

        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.X_AXIS));

        leftPanel.setBackground(Color.gray);
        leftPanel.setBorder(BorderFactory.createLineBorder(Color.red));

        rightPanel.setBackground(Color.yellow);
        rightPanel.setBorder(BorderFactory.createLineBorder(Color.CYAN));

        // LEFT AREA BUTTONS
        String[] arry = { "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
                "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
                "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
                "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
                "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
                "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
                "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
                "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
                "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
                "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
                "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
                "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
                "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
                "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
                "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000" };
        for (int i = 0; i < arry.length; i++) {
            JButton button = new JButton(arry[i]);
            leftPanel.add(button);

        }

        String[] arry2 = { "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW",
                "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN",
                "TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN", "TURBO" };

        for (int i = 0; i < arry2.length; i++) {
            JLabel labels = new JLabel(arry2[i]);
            rightPanel.add(labels);
        }

        // The problem I suspect is here because of course if I set the height
        // then the scroll will not work anymore. If I don't set up the sizes
        // then the first FlowLayout will cover 100% of the main JPanel.
        leftPanel.setMaximumSize(new Dimension(600, 600));
        leftPanel.setMinimumSize(new Dimension(600, 600));
        leftPanel.setPreferredSize(new Dimension(600, 600));

        rightPanel.setMaximumSize(new Dimension(200, 600));
        rightPanel.setMinimumSize(new Dimension(200, 600));
        rightPanel.setPreferredSize(new Dimension(200, 600));

        mainPanel.add(leftPanel);
        mainPanel.add(rightPanel);

        JScrollPane pane = new JScrollPane(mainPanel);

        frame.add(pane);

        frame.setVisible(true);

    }

    void setDimm() {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 600);
        frame.getContentPane().setBackground(Color.white);
        toolkit = frame.getToolkit();
        Dimension size = toolkit.getScreenSize();
        frame.setLocation((size.width - frame.getWidth()) / 2, (size.height - frame.getHeight()) / 2);

    }

}

该死的这些流布局。我不知道我的回答是否是完成它的最佳方式(我不喜欢)但它似乎有效。您可以 use a JSplitPane. 代替带有 BoxLayout X 轴的外部面板。它允许用户选择 right/left 面板的百分比。但是,如果您坚持使用 70% 的百分比,则必须向您的框架添加一个 ComponentListener#componentResized 侦听器以保持该百分比。代码中的一些注释。我尝试了很多变体,但似乎只有这个效果很好。尝试多花点时间修改我所做的,忘记在评论中提及。

public class Alignments { //Class names should start with an uppercase :)
    private JFrame frame;
    private JPanel leftPanel, rightPanel;

    public static void main(String[] args) {
        //All swing apps must run on their own thread
        SwingUtilities.invokeLater(() -> {
            Alignments align = new Alignments();
        });
    }

    public Alignments() {
        frame = new JFrame();
        frame.setLayout(new BorderLayout());

        leftPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5));
        rightPanel = new JPanel(new FlowLayout());

        leftPanel.setBackground(Color.gray);
        leftPanel.setBorder(BorderFactory.createLineBorder(Color.red));

        rightPanel.setBackground(Color.yellow);
        rightPanel.setBorder(BorderFactory.createLineBorder(Color.CYAN));

        // LEFT AREA BUTTONS
        String[] arry = { "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON",
                "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON",
                "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON",
                "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON",
                "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON",
                "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON",
                "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON",
                "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON",
                "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON",
                "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON",
                "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON",
                "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON",
                "40001", "40001", "40001", "40001", "40001", "40001", "40001", "40001", "40001", "40003" };
        for (int i = 0; i < arry.length; i++) {
            JButton button = new JButton(arry[i]);
            leftPanel.add(button);

        }

        String[] arry2 = { "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN",
                "TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN",
                "TURBO", "WOW", "MEGA FAIN", "TURBO" };

        for (int i = 0; i < arry2.length; i++) {
            JLabel labels = new JLabel(arry2[i]);
            rightPanel.add(labels);
        }

        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
        splitPane.setLeftComponent(leftPanel);
        splitPane.setRightComponent(rightPanel);
        splitPane.setDividerSize(0); //User cannot move the divider

        JScrollPane scrollPane = new JScrollPane(splitPane);

        frame.add(scrollPane);
        frame.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                int width = frame.getWidth() * 70 / 100; //70% of frame's width
                splitPane.setDividerLocation(width);

                Component comp = getComponentWithBiggestHeight(leftPanel);
                if (comp != null) {
                    int trueHeightOfLeftPanel = comp.getBounds().y + comp.getHeight() + 5; //+ some bottom insets? 
                    //Setting splitPane's width to 1 will make it being wrapped horizontally
                    splitPane.setPreferredSize(new Dimension(1, trueHeightOfLeftPanel));
                }
            }
        });
        setDimm();
        frame.setVisible(true);

    }

    private Component getComponentWithBiggestHeight(JPanel panel) {
        Component component = null;
        int max = -1;
        for (Component c : panel.getComponents()) {
            if (c.getBounds().y > max) {
                component = c;
            }
        }
        return component;
    }

    public void setDimm() {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 600);
        frame.getContentPane().setBackground(Color.white);
        frame.setLocationRelativeTo(null); //to the center of the screen
    }
}

小预览: