关于布局管理器,如何填充剩余 space?
How to fill left over space regarding Layout Managers?
我最近一直在开发一个Swing应用程序。我 运行 遇到了布局管理器的问题。我似乎无法弄清楚如何使布局中的组件一直增长到其父容器的边缘。让我解释一下。
假设我一排有 8 个按钮。根据window的大小决定是否占满space。 GBL 我找到了中心,所以 space 在左边和右边。 BoxLayout 通常 space 在右侧。这可能是由于它们的锚点或对齐方式。
我认为问题在于,当所有组件都具有相同设置时,布局会尝试为每个组件提供相同的设置 space。因此,额外的 space 不能平均分配给他们遗漏的每个组件。
我想知道是否有解决此问题的方法。就像 space 太小了,我希望有一种方法可以让最后一个组件吃掉它或者在组件之间尽可能地划分它。
这是显示问题的示例代码。请注意,当您调整面板大小时,您会得到额外的 space.
public class LeftoverExample {
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
LeftoverExample.createGUI();
}
});
}
public static void createGUI(){
JFrame jF = new JFrame();
jF.setSize(new Dimension(1333,500));
jF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create ContentPane
JPanel contentPane = new JPanel();
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.X_AXIS));
GridBagLayout gBL = new GridBagLayout();
gBL.columnWidths = new int[]{0};
gBL.rowHeights = new int[]{50, 50, 50 , 50};
contentPane.setLayout(gBL);
//Initial Constraints
GridBagConstraints gBC = new GridBagConstraints();
gBC.fill = GridBagConstraints.BOTH;
gBC.gridx = 0;
gBC.gridy = 0;
gBC.weightx = 1;
gBC.weighty = 0;
gBC.insets = new Insets(10, 0, 10, 0);
//Add Examples to ContentPane
contentPane.add(LeftoverExample.createGBL(false), gBC);
gBC.gridy++;
contentPane.add(LeftoverExample.createGBL(true), gBC);
gBC.gridy++;
contentPane.add(LeftoverExample.createBoxLayout(false), gBC);
gBC.gridy++;
contentPane.add(LeftoverExample.createBoxLayout(true), gBC);
//Final
jF.setContentPane(contentPane);
jF.setVisible(true);
}
private static JComponent createGBL(boolean addButtons){
//GBL Example
JLabel gBLJLabel = new JLabel("GridBagLayout");
gBLJLabel.setVerticalAlignment(SwingConstants.CENTER);
gBLJLabel.setLayout(new BoxLayout(gBLJLabel, BoxLayout.X_AXIS));
gBLJLabel.setBackground(Color.CYAN);
gBLJLabel.setOpaque(true);
gBLJLabel.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
GridBagLayout gBL = new GridBagLayout();
gBL.columnWidths = new int[]{0};
gBL.rowHeights = new int[]{50};
gBLJLabel.setLayout(gBL);
//Initial Constraints
GridBagConstraints gBC = new GridBagConstraints();
gBC.fill = GridBagConstraints.BOTH;
gBC.gridx = 0;
gBC.gridy = 0;
gBC.weightx = 1;
gBC.weighty = 0;
gBC.insets = new Insets(0, 0, 0, 0);
//Add to GBL Panel
if(addButtons){
LeftoverExample.addButtons(gBLJLabel, gBC);
LeftoverExample.addButtons(gBLJLabel, gBC);
LeftoverExample.addButtons(gBLJLabel, gBC);
LeftoverExample.addButtons(gBLJLabel, gBC);
LeftoverExample.addButtons(gBLJLabel, gBC);
LeftoverExample.addButtons(gBLJLabel, gBC);
}
return gBLJLabel;
}
private static JComponent createBoxLayout(boolean addButtons){
//BoxLayout Example
JLabel boxLayoutJL = new JLabel("BOX_LAYOUT");
boxLayoutJL.setVerticalAlignment(SwingConstants.CENTER);
boxLayoutJL.setLayout(new BoxLayout(boxLayoutJL, BoxLayout.X_AXIS));
boxLayoutJL.setBackground(Color.GREEN);
boxLayoutJL.setOpaque(true);
boxLayoutJL.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
//Add to BoxLayout Panel
if(addButtons){
LeftoverExample.addButtons(boxLayoutJL);
LeftoverExample.addButtons(boxLayoutJL);
LeftoverExample.addButtons(boxLayoutJL);
}
return boxLayoutJL;
}
private static JButton createButton(Color c){
JButton jB = new JButton();
jB.setBackground(c);
jB.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
return jB;
}
private static void addButtons(JComponent jC, GridBagConstraints gBC){
//Create Buttons
Color[] colorA = {Color.RED, Color.BLUE, Color.BLACK, Color.GREEN};
for(Color c : colorA){
jC.add(LeftoverExample.createButton(c), gBC);
gBC.gridx++;
}
}
private static void addButtons(JComponent jC){
//Create Buttons
Color[] colorA = {Color.BLUE, Color.BLACK, Color.GREEN, Color.RED};
for(Color c : colorA){
jC.add(LeftoverExample.createButton(c));
}
}
}
看看西侧和东侧如何有一些 space 被父级(在本例中为 JLabel)占用但按钮没有占用。我也希望能够让按钮占用 space。
图片示例:
问题是由 Swing 使用整数值而不是双精度值引起的。
考虑到这一点,容器宽度除以容器数量 Component
的余数 r(在您的情况下 JButton
objects) 它包含的对象可用于将第一个 r Component
个对象的大小增加 1 以进行补偿。显然这意味着第一个 r Component
个对象将比另一个 Components
大 +1,但这应该不会引起注意。
为了更新 Component
对象的宽度,我们需要访问那里的容器(例如 JPanel
)和我们希望更新的所有 Component
对象。在我的示例中,我将为此目的使用 List
。
这是一种相应地调整 Component
对象大小的方法。
private static void fixComponentWidths(Component container,
List<? extends Component> componentList, int componentHeight) {
if (!componentList.isEmpty()) { // Avoid possible division by zero
// get the desired component width for the container using integer division
int baseComponentWidth = container.getWidth() / componentList.size();
// find the remainder
int remainder = container.getWidth() % componentList.size();
// update all the components
for (int i = 0; i < componentList.size(); i++) {
// the component width will be the base width plus 1 iff i < remainder
int componentWidth = baseComponentWidth;
if (i < remainder) {
componentWidth++;
}
// update the maximum size
componentList.get(i).setMaximumSize(new Dimension(componentWidth, componentHeight));
}
// be sure to revalidate otherwise it may not work
container.revalidate();
}
}
为了使其在调整大小时起作用,必须为我们的容器实施 ComponentListener
。这可以是 JFrame
也可以只是 JPanel
(按照我的示例)。请注意,只有 componentResized(ComponentEvent)
方法需要为此任务实施。
buttonContainer.addComponentListener(new ComponentListener() {
@Override
public void componentResized(ComponentEvent ce) { // just implementing this
fixComponentWidths(buttonContainer, buttons, BUTTON_HEIGHT);
// where buttonContainer is a JPanel,
// buttons is a List of JButtons
// BUTTON_HEIGHT, well the height of the button!
}
@Override
public void componentMoved(ComponentEvent ce) { // not needed
}
@Override
public void componentShown(ComponentEvent ce) { // not needed
}
@Override
public void componentHidden(ComponentEvent ce) { // not needed
}
});
这就是所有需要的。但为了完整起见,这里有一个小例子,基于作者的问题,然后是 JPanel
的子 class,它使用 BoxLayout
来解决 [=30] 的这种行为=] 和 BoxLayout.Y_AXIS
.
完整示例
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class FillExample extends JFrame {
private static final int FRAMEL_DEFAULT_WIDTH = 700;
private static final int FRAME_DEFAULT_HEIGHT = 400;
private static final int BUTTON_HEIGHT = Integer.MAX_VALUE;
private final List<JButton> buttons;
public FillExample() {
buttons = new ArrayList<>();
}
public void createAndShow() {
setTitle("Fill Example");
setSize(FRAMEL_DEFAULT_WIDTH, FRAME_DEFAULT_HEIGHT);
final JPanel buttonContainer = new JPanel();
buttonContainer.setLayout(new BoxLayout(buttonContainer, BoxLayout.X_AXIS));
for (int i = 0; i < 3; i++) {
addButtons(buttonContainer);
}
getContentPane().add(buttonContainer);
buttonContainer.addComponentListener(new ComponentListener() {
@Override
public void componentResized(ComponentEvent ce) {
fixComponentWidths(buttonContainer, buttons, BUTTON_HEIGHT);
}
@Override
public void componentMoved(ComponentEvent ce) {
}
@Override
public void componentShown(ComponentEvent ce) {
}
@Override
public void componentHidden(ComponentEvent ce) {
}
});
setVisible(true);
}
private static void fixComponentWidths(Component container, List<? extends Component> componentList, int componentHeight) {
if (!componentList.isEmpty()) {
int baseComponentWidth = container.getWidth() / componentList.size();
int remainder = container.getWidth() % componentList.size();
for (int i = 0; i < componentList.size(); i++) {
int componentWidth = baseComponentWidth;
if (i < remainder) {
componentWidth++;
}
componentList.get(i).setMaximumSize(new Dimension(componentWidth, componentHeight));
}
container.revalidate();
}
}
private void addButtons(JComponent component) {
Color[] colorA = {Color.RED, Color.BLUE, Color.BLACK, Color.GREEN};
for (Color c : colorA) {
JButton button = createButton(c);
buttons.add(button);
component.add(button);
}
}
private static JButton createButton(Color color) {
JButton button = new JButton();
button.setBackground(color);
button.setMaximumSize(new Dimension(Integer.MAX_VALUE, BUTTON_HEIGHT));
return button;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new FillExample().createAndShow();
}
});
}
}
FillBoxLayoutPanel
这个小 class 可用于快速解决 BoxLayout.X_AXIS
和 BoxLayout.Y_AXIS
的间距问题。请注意,class 创建 BoxLayout
并且 LayoutManager
无法更改。
Component
对象可以使用 add(Component comp)
和 add(Component comp, int index)
添加到面板。请注意,并非所有 add
方法都被覆盖,class 应谨慎使用。
import java.awt.Component;
import java.awt.Dimension;
import java.awt.LayoutManager;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
public class FillBoxLayoutPanel extends JPanel {
public static final int X_AXIS = BoxLayout.X_AXIS;
public static final int Y_AXIS = BoxLayout.Y_AXIS;
private final List<Component> components;
private final int direction;
private boolean layoutSet;
public FillBoxLayoutPanel(int direction) {
components = new ArrayList<>();
this.direction = direction;
setLayout(new BoxLayout(this, direction));
layoutSet = true;
addComponentListener(new ComponentListener() {
@Override
public void componentResized(ComponentEvent ce) {
adjustComponents();
}
@Override
public void componentMoved(ComponentEvent ce) {
}
@Override
public void componentShown(ComponentEvent ce) {
}
@Override
public void componentHidden(ComponentEvent ce) {
}
});
}
@Override
public void setLayout(LayoutManager mgr) {
if (layoutSet) {
throw new UnsupportedOperationException("FillPanel's layout manager cannot be changed.");
} else {
super.setLayout(mgr);
}
}
@Override
public Component add(Component comp) {
comp = super.add(comp);
components.add(comp);
return comp;
}
@Override
public Component add(Component comp, int i) {
comp = super.add(comp, i);
components.add(i, comp);
return comp;
}
private void adjustComponents() {
if (!components.isEmpty()) {
int size = direction == X_AXIS ? getWidth() : getHeight();
int baseComponentSize = size / components.size();
int remainder = size % components.size();
for (int i = 0; i < components.size(); i++) {
int componentSize = baseComponentSize;
if (i < remainder) {
componentSize++;
}
Dimension dimension;
if (direction == X_AXIS) {
dimension = new Dimension(componentSize, components.get(i).getHeight());
} else {
dimension = new Dimension(components.get(i).getWidth(), componentSize);
}
components.get(i).setMaximumSize(dimension);
}
revalidate();
}
}
}
I think the problem is because the Layouts when all components have same settings it tries to give each component same space. So that little extra space can't be divided up equally to each component they leave it out.
也许你可以使用 Relative Layout。
它可以让您轻松地使每个组件大小相同。
然后它有一个 属性 允许您确定在需要时应如何分配额外的像素。
我最近一直在开发一个Swing应用程序。我 运行 遇到了布局管理器的问题。我似乎无法弄清楚如何使布局中的组件一直增长到其父容器的边缘。让我解释一下。
假设我一排有 8 个按钮。根据window的大小决定是否占满space。 GBL 我找到了中心,所以 space 在左边和右边。 BoxLayout 通常 space 在右侧。这可能是由于它们的锚点或对齐方式。
我认为问题在于,当所有组件都具有相同设置时,布局会尝试为每个组件提供相同的设置 space。因此,额外的 space 不能平均分配给他们遗漏的每个组件。
我想知道是否有解决此问题的方法。就像 space 太小了,我希望有一种方法可以让最后一个组件吃掉它或者在组件之间尽可能地划分它。
这是显示问题的示例代码。请注意,当您调整面板大小时,您会得到额外的 space.
public class LeftoverExample {
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
LeftoverExample.createGUI();
}
});
}
public static void createGUI(){
JFrame jF = new JFrame();
jF.setSize(new Dimension(1333,500));
jF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create ContentPane
JPanel contentPane = new JPanel();
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.X_AXIS));
GridBagLayout gBL = new GridBagLayout();
gBL.columnWidths = new int[]{0};
gBL.rowHeights = new int[]{50, 50, 50 , 50};
contentPane.setLayout(gBL);
//Initial Constraints
GridBagConstraints gBC = new GridBagConstraints();
gBC.fill = GridBagConstraints.BOTH;
gBC.gridx = 0;
gBC.gridy = 0;
gBC.weightx = 1;
gBC.weighty = 0;
gBC.insets = new Insets(10, 0, 10, 0);
//Add Examples to ContentPane
contentPane.add(LeftoverExample.createGBL(false), gBC);
gBC.gridy++;
contentPane.add(LeftoverExample.createGBL(true), gBC);
gBC.gridy++;
contentPane.add(LeftoverExample.createBoxLayout(false), gBC);
gBC.gridy++;
contentPane.add(LeftoverExample.createBoxLayout(true), gBC);
//Final
jF.setContentPane(contentPane);
jF.setVisible(true);
}
private static JComponent createGBL(boolean addButtons){
//GBL Example
JLabel gBLJLabel = new JLabel("GridBagLayout");
gBLJLabel.setVerticalAlignment(SwingConstants.CENTER);
gBLJLabel.setLayout(new BoxLayout(gBLJLabel, BoxLayout.X_AXIS));
gBLJLabel.setBackground(Color.CYAN);
gBLJLabel.setOpaque(true);
gBLJLabel.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
GridBagLayout gBL = new GridBagLayout();
gBL.columnWidths = new int[]{0};
gBL.rowHeights = new int[]{50};
gBLJLabel.setLayout(gBL);
//Initial Constraints
GridBagConstraints gBC = new GridBagConstraints();
gBC.fill = GridBagConstraints.BOTH;
gBC.gridx = 0;
gBC.gridy = 0;
gBC.weightx = 1;
gBC.weighty = 0;
gBC.insets = new Insets(0, 0, 0, 0);
//Add to GBL Panel
if(addButtons){
LeftoverExample.addButtons(gBLJLabel, gBC);
LeftoverExample.addButtons(gBLJLabel, gBC);
LeftoverExample.addButtons(gBLJLabel, gBC);
LeftoverExample.addButtons(gBLJLabel, gBC);
LeftoverExample.addButtons(gBLJLabel, gBC);
LeftoverExample.addButtons(gBLJLabel, gBC);
}
return gBLJLabel;
}
private static JComponent createBoxLayout(boolean addButtons){
//BoxLayout Example
JLabel boxLayoutJL = new JLabel("BOX_LAYOUT");
boxLayoutJL.setVerticalAlignment(SwingConstants.CENTER);
boxLayoutJL.setLayout(new BoxLayout(boxLayoutJL, BoxLayout.X_AXIS));
boxLayoutJL.setBackground(Color.GREEN);
boxLayoutJL.setOpaque(true);
boxLayoutJL.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
//Add to BoxLayout Panel
if(addButtons){
LeftoverExample.addButtons(boxLayoutJL);
LeftoverExample.addButtons(boxLayoutJL);
LeftoverExample.addButtons(boxLayoutJL);
}
return boxLayoutJL;
}
private static JButton createButton(Color c){
JButton jB = new JButton();
jB.setBackground(c);
jB.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
return jB;
}
private static void addButtons(JComponent jC, GridBagConstraints gBC){
//Create Buttons
Color[] colorA = {Color.RED, Color.BLUE, Color.BLACK, Color.GREEN};
for(Color c : colorA){
jC.add(LeftoverExample.createButton(c), gBC);
gBC.gridx++;
}
}
private static void addButtons(JComponent jC){
//Create Buttons
Color[] colorA = {Color.BLUE, Color.BLACK, Color.GREEN, Color.RED};
for(Color c : colorA){
jC.add(LeftoverExample.createButton(c));
}
}
}
看看西侧和东侧如何有一些 space 被父级(在本例中为 JLabel)占用但按钮没有占用。我也希望能够让按钮占用 space。
图片示例:
问题是由 Swing 使用整数值而不是双精度值引起的。
考虑到这一点,容器宽度除以容器数量 Component
的余数 r(在您的情况下 JButton
objects) 它包含的对象可用于将第一个 r Component
个对象的大小增加 1 以进行补偿。显然这意味着第一个 r Component
个对象将比另一个 Components
大 +1,但这应该不会引起注意。
为了更新 Component
对象的宽度,我们需要访问那里的容器(例如 JPanel
)和我们希望更新的所有 Component
对象。在我的示例中,我将为此目的使用 List
。
这是一种相应地调整 Component
对象大小的方法。
private static void fixComponentWidths(Component container,
List<? extends Component> componentList, int componentHeight) {
if (!componentList.isEmpty()) { // Avoid possible division by zero
// get the desired component width for the container using integer division
int baseComponentWidth = container.getWidth() / componentList.size();
// find the remainder
int remainder = container.getWidth() % componentList.size();
// update all the components
for (int i = 0; i < componentList.size(); i++) {
// the component width will be the base width plus 1 iff i < remainder
int componentWidth = baseComponentWidth;
if (i < remainder) {
componentWidth++;
}
// update the maximum size
componentList.get(i).setMaximumSize(new Dimension(componentWidth, componentHeight));
}
// be sure to revalidate otherwise it may not work
container.revalidate();
}
}
为了使其在调整大小时起作用,必须为我们的容器实施 ComponentListener
。这可以是 JFrame
也可以只是 JPanel
(按照我的示例)。请注意,只有 componentResized(ComponentEvent)
方法需要为此任务实施。
buttonContainer.addComponentListener(new ComponentListener() {
@Override
public void componentResized(ComponentEvent ce) { // just implementing this
fixComponentWidths(buttonContainer, buttons, BUTTON_HEIGHT);
// where buttonContainer is a JPanel,
// buttons is a List of JButtons
// BUTTON_HEIGHT, well the height of the button!
}
@Override
public void componentMoved(ComponentEvent ce) { // not needed
}
@Override
public void componentShown(ComponentEvent ce) { // not needed
}
@Override
public void componentHidden(ComponentEvent ce) { // not needed
}
});
这就是所有需要的。但为了完整起见,这里有一个小例子,基于作者的问题,然后是 JPanel
的子 class,它使用 BoxLayout
来解决 [=30] 的这种行为=] 和 BoxLayout.Y_AXIS
.
完整示例
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class FillExample extends JFrame {
private static final int FRAMEL_DEFAULT_WIDTH = 700;
private static final int FRAME_DEFAULT_HEIGHT = 400;
private static final int BUTTON_HEIGHT = Integer.MAX_VALUE;
private final List<JButton> buttons;
public FillExample() {
buttons = new ArrayList<>();
}
public void createAndShow() {
setTitle("Fill Example");
setSize(FRAMEL_DEFAULT_WIDTH, FRAME_DEFAULT_HEIGHT);
final JPanel buttonContainer = new JPanel();
buttonContainer.setLayout(new BoxLayout(buttonContainer, BoxLayout.X_AXIS));
for (int i = 0; i < 3; i++) {
addButtons(buttonContainer);
}
getContentPane().add(buttonContainer);
buttonContainer.addComponentListener(new ComponentListener() {
@Override
public void componentResized(ComponentEvent ce) {
fixComponentWidths(buttonContainer, buttons, BUTTON_HEIGHT);
}
@Override
public void componentMoved(ComponentEvent ce) {
}
@Override
public void componentShown(ComponentEvent ce) {
}
@Override
public void componentHidden(ComponentEvent ce) {
}
});
setVisible(true);
}
private static void fixComponentWidths(Component container, List<? extends Component> componentList, int componentHeight) {
if (!componentList.isEmpty()) {
int baseComponentWidth = container.getWidth() / componentList.size();
int remainder = container.getWidth() % componentList.size();
for (int i = 0; i < componentList.size(); i++) {
int componentWidth = baseComponentWidth;
if (i < remainder) {
componentWidth++;
}
componentList.get(i).setMaximumSize(new Dimension(componentWidth, componentHeight));
}
container.revalidate();
}
}
private void addButtons(JComponent component) {
Color[] colorA = {Color.RED, Color.BLUE, Color.BLACK, Color.GREEN};
for (Color c : colorA) {
JButton button = createButton(c);
buttons.add(button);
component.add(button);
}
}
private static JButton createButton(Color color) {
JButton button = new JButton();
button.setBackground(color);
button.setMaximumSize(new Dimension(Integer.MAX_VALUE, BUTTON_HEIGHT));
return button;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new FillExample().createAndShow();
}
});
}
}
FillBoxLayoutPanel
这个小 class 可用于快速解决 BoxLayout.X_AXIS
和 BoxLayout.Y_AXIS
的间距问题。请注意,class 创建 BoxLayout
并且 LayoutManager
无法更改。
Component
对象可以使用 add(Component comp)
和 add(Component comp, int index)
添加到面板。请注意,并非所有 add
方法都被覆盖,class 应谨慎使用。
import java.awt.Component;
import java.awt.Dimension;
import java.awt.LayoutManager;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
public class FillBoxLayoutPanel extends JPanel {
public static final int X_AXIS = BoxLayout.X_AXIS;
public static final int Y_AXIS = BoxLayout.Y_AXIS;
private final List<Component> components;
private final int direction;
private boolean layoutSet;
public FillBoxLayoutPanel(int direction) {
components = new ArrayList<>();
this.direction = direction;
setLayout(new BoxLayout(this, direction));
layoutSet = true;
addComponentListener(new ComponentListener() {
@Override
public void componentResized(ComponentEvent ce) {
adjustComponents();
}
@Override
public void componentMoved(ComponentEvent ce) {
}
@Override
public void componentShown(ComponentEvent ce) {
}
@Override
public void componentHidden(ComponentEvent ce) {
}
});
}
@Override
public void setLayout(LayoutManager mgr) {
if (layoutSet) {
throw new UnsupportedOperationException("FillPanel's layout manager cannot be changed.");
} else {
super.setLayout(mgr);
}
}
@Override
public Component add(Component comp) {
comp = super.add(comp);
components.add(comp);
return comp;
}
@Override
public Component add(Component comp, int i) {
comp = super.add(comp, i);
components.add(i, comp);
return comp;
}
private void adjustComponents() {
if (!components.isEmpty()) {
int size = direction == X_AXIS ? getWidth() : getHeight();
int baseComponentSize = size / components.size();
int remainder = size % components.size();
for (int i = 0; i < components.size(); i++) {
int componentSize = baseComponentSize;
if (i < remainder) {
componentSize++;
}
Dimension dimension;
if (direction == X_AXIS) {
dimension = new Dimension(componentSize, components.get(i).getHeight());
} else {
dimension = new Dimension(components.get(i).getWidth(), componentSize);
}
components.get(i).setMaximumSize(dimension);
}
revalidate();
}
}
}
I think the problem is because the Layouts when all components have same settings it tries to give each component same space. So that little extra space can't be divided up equally to each component they leave it out.
也许你可以使用 Relative Layout。
它可以让您轻松地使每个组件大小相同。
然后它有一个 属性 允许您确定在需要时应如何分配额外的像素。