Изменение размера нескольких JPanels в соответствии с окном

#java #swing #jpanel #layout-manager #boxlayout

Вопрос:

Я довольно новичок в инструментарии Java Swing и создал серию JPanel JLabel компонентов, соответствующих индексу и значению каждой панели. Однако я, похоже, не могу правильно изменить размер панелей, когда окно слишком мало, чтобы изменить размер всех панелей сразу. В результате появляется дополнительное красное поле справа от всех панелей (см. Окно).

Есть ли способ изменить размер дополнительных панелей/разделительных панелей таким образом, чтобы не допускать дополнительного поля? Или настроить лучший макет качания для обработки такого изменения размера?

Демонстрация кода:

 import java.awt.*;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import javax.swing.BoxLayout;

public class Frame extends JFrame {
    private int numBox = 20;

    public class SubPanel extends JPanel {
        public SubPanel(int i) {
            setMinimumSize(new Dimension(20, 20));
            setMaximumSize(new Dimension(1000, i*30));
            setBackground(Color.BLACK);
            setLayout(new BorderLayout());
            setAlignmentY(Component.BOTTOM_ALIGNMENT);

            JLabel labelValue = new JLabel(String.valueOf(30 * i), JLabel.CENTER);
            labelValue.setForeground(Color.WHITE);
            add(labelValue, BorderLayout.NORTH);

            JLabel labelIndex = new JLabel(String.valueOf(i), JLabel.CENTER);
            labelIndex.setForeground(Color.WHITE);
            add(labelIndex, BorderLayout.SOUTH);
        }
    }

    public class SpacerPanel extends JPanel {
        public SpacerPanel() {
            setBackground(Color.WHITE);
            setMaximumSize(new Dimension(3, 10000));
            setMinimumSize(new Dimension(3, 0));
        }
    }

    public Frame(String title) {
        super(title);

        JPanel mainPanel = new JPanel();
        mainPanel.setBackground(Color.RED);
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.LINE_AXIS));

        for (int i = 1; i < numBox   1; i  ) {
            mainPanel.add(new SpacerPanel());
            mainPanel.add(new SubPanel(i));
        }
        mainPanel.add(new SpacerPanel());

        add(mainPanel);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main(String[] args) {
        new Frame("Frame").setSize(1200, 700);
    }
}
 

Ответ №1:

Если у вас 40 компонентов и вы изменяете размер кадра на несколько пикселей, у BoxLayout возникают проблемы с распределением этих пикселей для каждого из компонентов.

Вместо этого вы можете использовать Относительный макет, который позволяет указать, как должны быть распределены эти пиксели.

Это RelativeLayout также позволяет указать зазор между каждым компонентом, поэтому вам не нужно добавлять разделительную панель.

Однако вам нужно будет изменить логику «подпанели». Высоту этикеток необходимо зафиксировать, чтобы их можно было покрасить в черный цвет. Поэтому я создал «Панель этикеток» для хранения этикеток.

Реструктурированный код с использованием RelativeLayout будет:

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

import javax.swing.BoxLayout;

public class Frame extends JFrame {
    private int numBox = 20;

    public class SubPanel extends JPanel {
        public SubPanel(int i) {
//            setMinimumSize(new Dimension(20, 20));
//            setMaximumSize(new Dimension(1000, i*30));
//            setPreferredSize(new Dimension(20, i*30));
            setBackground(Color.RED);
            setLayout(new BorderLayout());
//            setAlignmentY(Component.BOTTOM_ALIGNMENT);

            JPanel labelPanel = new JPanel( new BorderLayout() );
            labelPanel.setBackground( Color.BLACK );
            labelPanel.setPreferredSize(new Dimension(20, i*30));
            add(labelPanel, BorderLayout.PAGE_END);

            JLabel labelValue = new JLabel(String.valueOf(30 * i), JLabel.CENTER);
            labelValue.setForeground(Color.WHITE);
            labelPanel.add(labelValue, BorderLayout.NORTH);

            JLabel labelIndex = new JLabel(String.valueOf(i), JLabel.CENTER);
            labelIndex.setForeground(Color.WHITE);
            labelPanel.add(labelIndex, BorderLayout.SOUTH);
        }
    }

    public class SpacerPanel extends JPanel {
        public SpacerPanel() {
            setBackground(Color.WHITE);
            setMaximumSize(new Dimension(3, 10000));
            setMinimumSize(new Dimension(3, 0));
        }
    }

    public Frame(String title) {
        super(title);

        JPanel mainPanel = new JPanel();
//        mainPanel.setBackground(Color.RED);
        mainPanel.setBackground(Color.WHITE);

//        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.LINE_AXIS));
        RelativeLayout rl = new RelativeLayout(RelativeLayout.X_AXIS, 5);
        rl.setFill( true );
        rl.setRoundingPolicy(RelativeLayout.EQUAL);
        rl.setAlignment(RelativeLayout.TRAILING);
        mainPanel.setLayout( rl );
        Float constraint = new Float(1);

        for (int i = 1; i < numBox   1; i  ) {
//            mainPanel.add(new SpacerPanel());
//            mainPanel.add(new SubPanel(i));
            mainPanel.add(new SubPanel(i), constraint);
        }
//        mainPanel.add(new SpacerPanel());

        add(mainPanel);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main(String[] args) {
        new Frame("Frame").setSize(1200, 700);
    }
}
 

Или этот подход ближе к вашей первоначальной публикации. Он по-прежнему использует распорку, и высота черных столбцов будет уменьшаться по мере уменьшения высоты рамки:

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

import javax.swing.BoxLayout;

public class Frame2 extends JFrame {
    private int numBox = 20;

    public class SubPanel extends JPanel {
        public SubPanel(int i) {
//            setMinimumSize(new Dimension(20, 20));
//            setMaximumSize(new Dimension(1000, i*30));
//            setBackground(Color.BLACK);
            setBackground(Color.RED);
//            setLayout(new BorderLayout());
            setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
            add(Box.createVerticalGlue());
//            setAlignmentY(Component.BOTTOM_ALIGNMENT);

            JPanel labelPanel = new JPanel();
            labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.Y_AXIS));
            labelPanel.setBackground( Color.BLACK );
            labelPanel.setPreferredSize(new Dimension(50, i*30));
            labelPanel.setMaximumSize(new Dimension(1000, labelPanel.getPreferredSize().height));
            add(labelPanel, BorderLayout.CENTER);

            JLabel labelValue = new JLabel(String.valueOf(30 * i), JLabel.CENTER);
            labelValue.setForeground(Color.WHITE);
            labelValue.setAlignmentX(JLabel.CENTER_ALIGNMENT);
//            add(labelValue, BorderLayout.NORTH);
            labelPanel.add(labelValue);

            labelPanel.add(Box.createVerticalGlue());

            JLabel labelIndex = new JLabel(String.valueOf(i), JLabel.CENTER);
            labelIndex.setForeground(Color.WHITE);
            labelIndex.setAlignmentX(JLabel.CENTER_ALIGNMENT);
//            add(labelIndex, BorderLayout.SOUTH);
            labelPanel.add(labelIndex);
        }
    }

    public class SpacerPanel extends JPanel {
        public SpacerPanel() {
            setBackground(Color.WHITE);
            setMaximumSize(new Dimension(3, 10000));
            setMinimumSize(new Dimension(3, 0));
        }
    }

    public Frame2(String title) {
        super(title);

        JPanel mainPanel = new JPanel();
        mainPanel.setBackground(Color.RED);
//        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.LINE_AXIS));
        RelativeLayout rl = new RelativeLayout(RelativeLayout.X_AXIS, 0);
        rl.setFill( true );
        rl.setRoundingPolicy(RelativeLayout.EQUAL);
        rl.setAlignment(RelativeLayout.TRAILING);
        mainPanel.setLayout( rl );
        Float constraint = new Float(1);

        for (int i = 1; i < numBox   1; i  ) {
            mainPanel.add(new SpacerPanel());
//            mainPanel.add(new SubPanel(i));
            mainPanel.add(new SubPanel(i), constraint);
        }
        mainPanel.add(new SpacerPanel());

        add(mainPanel);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main(String[] args) {
        new Frame2("Frame").setSize(1200, 700);
    }
}