如何使我的 JScrollBar 工作或动态调整 JPanel 的大小以适应组件?

How to make my JScrollBar work or dynamically resize a JPanel to fit components?

我已经彻底搜索了我的问题的答案并尝试了多种方法,但 none 这些方法对我有用。

我有一个打开 JDialog 的按钮,允许用户为三种 objects/constraints.

属性和更改颜色

JDialog 由 2 个 JPanels 组成,第一个包含另外 3 个 JPanels 用于所有三种类型的对象,第二个包含 OK/Cancel 按钮。

我的问题是所谓的第三类对象"Label constraints"。

这第三种类型的对象可以有子对象,这些子对象在用户创建时动态添加到 JPanel 中,由名称和用于更改对象颜色的按钮组成。

此方法创建了一个 JPanel,其中包含文本和一个用于选择对象颜色的按钮,并将其添加到 labelColorConstraintPanel,这是 [=77= 的一个字段].此方法在负责创建对象的另一个方法中调用。

 /**
 * Add the last created label constraint class name(number) and its color
 * button to the panel labelColorConstraintPanel. The button allows user to
 * choose the label constraint class color.
 **/
protected void createLabelColorConstraintsPanel() {

    // labelColorConstraintPanel
    JPanel classNameButtonPanel = new JPanel(new GridLayout(0, 2));
// classNameButtonPanel.setPreferredSize(new Dimension(15, 20));
    classNameButtonPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));

    classNameButtonPanel.add(new JLabel("Class " + labelClassesCount + ":"));
    jb_labelConstraintClassChooseColor.get(labelClassesCount - 1).addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent event) {

            JButton lblClassColorButtonClicked = (JButton) event.getSource();
            int buttonIndex = (int) lblClassColorButtonClicked.getClientProperty("index");
            chooseLabelClassColor(buttonIndex);
        }
    });
    classNameButtonPanel.add(jb_labelConstraintClassChooseColor.get(labelClassesCount - 1));

    labelColorConstraintPanel.add(classNameButtonPanel);
}

labelColorConstraintPanel 附加到 JScrollPane,后者附加到另一个 JPanel 以用于第三类对象 - 标签约束。

我的问题是 JScrollPane 上的 JScrollBar 不会出现。 但是我读到将 JScrollPaneJPanelpreferredSize 设置为大于这一秒的大小将使垂直条出现(参见方法 chooseConstraintsColors 中的注释代码行).

通过这种方式,我成功地把bar show搞定了,但是还有另外两个问题。 第一个:第一个按钮在 JPanel 创建巨大按钮的总数上添加了拉伸。

第二个:我添加的按钮越多,它们的大小就会调整,有时行会变得 "crowded".

最后我想这 2 个问题代表同一个问题,但是我似乎找不到解决方案。

要么有另一种方法来显示 JScrollBar 而无需设置 preferredSize(),或者有一种方法可以在我们添加新对象时动态增加 JPanel 的大小它具有固定大小。

这是创建 JDialog window:

的主要方法
/** Opens a JDialog for choosing the Constraints Colors **/
protected void chooseConstraintColors() {

    jd_colorsChooser = new JDialog((Frame) this.getTopLevelAncestor(), "Choose Constraints Colors", true);
    jd_colorsChooser.getRootPane().setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
    jd_colorsChooser.setLayout(new BorderLayout());

    JPanel constraintsPanel = new JPanel(new BorderLayout());
    JPanel mlConstraintsPanel = new JPanel();
    JPanel clConstraintsPanel = new JPanel();
    JPanel lblConstraintsPanel=new JPanel(new GridLayout(0,1));

    JScrollPane lblConstraintsPane = new JScrollPane(labelColorConstraintPanel,
            ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    lblConstraintsPane.setPreferredSize(new Dimension(130,130));
    TitledBorder lblcBorder = BorderFactory.createTitledBorder(
            BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), "Label Constraints Color", TitledBorder.LEFT,
            TitledBorder.TOP);
    lblConstraintsPane.setBorder(lblcBorder);

    // must-link constraints panel
    mlConstraintsPanel.setLayout(new BorderLayout());
    TitledBorder mlcBorder = BorderFactory.createTitledBorder(
            BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), "Must-Link Constraints Color",
            TitledBorder.LEFT, TitledBorder.TOP);
    mlConstraintsPanel.setBorder(mlcBorder);
    jb_mustLinkChooseColor.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            chooseMustLinkColor();
        }

    });
    mlConstraintsPanel.add(jb_mustLinkChooseColor, BorderLayout.CENTER);

    // cannot-link constraints panel
    clConstraintsPanel.setLayout(new BorderLayout());
    TitledBorder clcBorder = BorderFactory.createTitledBorder(
            BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), "Cannot-Link Constraints Color",
            TitledBorder.LEFT, TitledBorder.TOP);
    clConstraintsPanel.setBorder(clcBorder);
    jb_cannotLinkChooseColor.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            chooseCannotLinkColor();
        }
    });
    clConstraintsPanel.add(jb_cannotLinkChooseColor, BorderLayout.CENTER);

    // label constraints panel
     labelColorConstraintPanel.setPreferredSize(new Dimension(131,131));
     lblConstraintsPanel.add(lblConstraintsPane);

    constraintsPanel.add(mlConstraintsPanel, BorderLayout.NORTH);
    constraintsPanel.add(clConstraintsPanel, BorderLayout.CENTER);
    constraintsPanel.add(lblConstraintsPanel, BorderLayout.SOUTH);

    // button panel
    JPanel buttonPanel = new JPanel();
    JButton ok = new JButton("OK");// update color changes on ok, update
                                    // only fields that have changed
    ok.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent event) {

            if (mustLinkColorTemp != null && mustLinkColorTemp != mustLinkColor) {
                mustLinkColor = mustLinkColorTemp;
                jb_mustLinkChooseColor.setBackground(mustLinkColor);
            }

            if (cannotLinkColorTemp != null && cannotLinkColorTemp != cannotLinkColor) {
                cannotLinkColor = cannotLinkColorTemp;
                jb_cannotLinkChooseColor.setBackground(cannotLinkColor);

            }

            for (int i = 0; i < labelClassesCount; i++) {
                if (labelConstraintColorTemp.get(i) != null
                        && labelConstraintColorTemp.get(i) != labelConstraintColor.get(i)) {

                    labelConstraintColor.set(i, labelConstraintColorTemp.get(i));
                    jb_labelConstraintClassChooseColor.get(i).setBackground(labelConstraintColor.get(i));
                }

            }

            jd_colorsChooser.dispose();
        }
    });

    // exit dialog on cancel
    JButton cancel = new JButton("Cancel");
    cancel.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent event) {

            jb_mustLinkChooseColor.setBackground(mustLinkColor);
            jb_cannotLinkChooseColor.setBackground(cannotLinkColor);
            for (int i = 0; i < labelClassesCount; i++) {

                jb_labelConstraintClassChooseColor.get(i).setBackground(labelConstraintColor.get(i));
            }
            jd_colorsChooser.dispose();
        }
    });

    buttonPanel.add(ok);
    buttonPanel.add(cancel);

    jd_colorsChooser.add(constraintsPanel, BorderLayout.NORTH);
    jd_colorsChooser.add(buttonPanel, BorderLayout.SOUTH);

    jd_colorsChooser.setPreferredSize(new Dimension(270, 270));
    jd_colorsChooser.pack();
    jd_colorsChooser.setLocationRelativeTo(null);
    jd_colorsChooser.setVisible(true);
}

P.S: 由于我是 Whosebug 的新手,我真的不会上传图片,但这里是图片的描述:

案例 1:JDialog 有 3 个面板和一个确定按钮和一个取消按钮。

如果setPreferredSize不使用,则在第三个JPanel中依次添加按钮,不出现滚动条。

案例 2:使用 setPrefferedSize(),出现滚动条,第一个按钮拉伸超过 JPanel 的大小,因为我们添加更多按钮行 JPanel 的按钮变得拥挤。

In this way I managed to make the bar show, but I have two other problems. The first one: first buttons added stretch on the total of the JPanel creating enormous buttons. The second one: the more buttons I add, they're resized and at some point the rows get "crowded"

  1. 不要使用 setPreferredSize()。计算首选大小是布局管理器的工作。

  2. 您使用了错误的布局管理器。您永远不会被迫使用可以嵌套布局管理器的单个布局管理器。例如,您可以创建一个带有 BorderLayout 的 JPanel,并将此面板添加到 scrollPane。然后使用 GridLayout 创建第二个面板,并使用 BorderLayout 创建面板的 BorderLayout.PAGE_START。现在面板将尊重添加到它的组件的大小并根据需要增长。