我觉得在我看来应该是一个非常简单的问题。在我看来,这只是对制作GridBagLayout的人的大规模监督...

无论如何。我正在使用GridBagLayout为正在制作的游戏显示27x13的瓷砖网格。我之所以使用这种布局,是因为它可以调整组件的大小,并且配置起来也很容易,但是只有一个小问题。调整图块大小时,如果宽度不是27的倍数,或者高度不是13的倍数,则边框周围会有空白。

为了表明我的意思:

Here是我调整框架大小时的外观,以使其中的JPanel尺寸为864x416,是27和13的完美倍数。

Here就是我调整框架大小的样子,以使其中的JPanel尺寸为863x415,几乎不是27或13的倍数。

它只是没有在图块之间分配额外的像素。我不知道为什么当我使用它们各自的方法来摆弄最小/最大/首选大小或覆盖它们时,甚至使用GridBagLayoutipadxipady约束时,我都可以删除空白-但它所做的只是挤压最外面的瓷砖以适合其余部分。您可以在下面的示例代码中看到它。

这是一个SSCCE:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.Random;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Game extends JPanel {
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                start();
            }
        });
    }
    static void start() {
        JFrame frame = new JFrame("Game");
        JPanel newFrame = new MainGameScreen();
        frame.getContentPane().add(newFrame);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
class MainGameScreen extends JPanel {
    public MainGameScreen() {
        setPreferredSize(new Dimension(864, 551));
        setLayout(new GridBagLayout());
        setBackground(Color.green);
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.BOTH;
        gbc.weightx = 1;
        gbc.weighty = 1;
        gbc.ipadx = 0; //Change to 64 to see undesired effects
        gbc.ipady = 0; //^
        for (int i=0;i<13;i++) {
            for (int j=0;j<27;j++) {
                gbc.gridx = j;
                gbc.gridy = i;
                add(new ImagePanel(), gbc);
            }
        }
    }
}
class ImagePanel extends JComponent {
    private int r,g,b;
    public ImagePanel() {
        Random generator = new Random();
        r = generator.nextInt(100)+1;
        g = generator.nextInt(100)+1;
        b = generator.nextInt(100)+1;
    }
    @Override
    public void paintComponent(Graphics gr) {
        super.paintComponent(gr);
        gr.setColor(new Color(r,g,b));
        gr.fillRect(0, 0, getWidth(), getHeight());
    }
}


我的问题是,如何使布局始终看起来像第一个图像?我需要其他布局吗?我在这里很迷路。

最佳答案

我将使用带有正方形瓷砖的面板使用GridLayout,并将其嵌套在窗口其余部分的另一个布局(GridBagLayout,BorderLayout,BoxLayout或布局的某种组合)内。

也就是说,在这种情况下,GridLayout和GridBagLayout都将均匀分布像素。由于您只能使用整个像素,因此,在将空间划分为零后,您将剩下剩余的部分,并将其用作填充。尽管有一些潜在的解决方法,但这在很大程度上是不可避免的:


强制某些窗口大小
绘制比您需要的面板更大的面板,但是使用视口,以便多余的图块在视图中被截断
在平铺区域的边界添加其他元素,以有效隐藏存在额外填充的事实


如果您对第一个选项没问题,可以稍作修改以将窗口捕捉到兼容的大小,这样就没有余数了(注意:我也将几个硬编码的int更改为常量):

package com.example.game;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Random;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

    public class Game extends JPanel {
        public static void main(String[] args) {
            javax.swing.SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    start();
                }
            });
        }

        static void start() {
            final JFrame frame = new JFrame("Game");
            JPanel newFrame = new MainGameScreen();

            frame.addComponentListener(new ComponentAdapter() {
                @Override
                public void componentResized(ComponentEvent e) {
                    int h = frame.getContentPane().getHeight() % MainGameScreen.ROWS;
                    int w = frame.getContentPane().getWidth() % MainGameScreen.COLS;

                    // Subtract the remainder pixels from the size.
                    frame.setSize(frame.getWidth() - w, frame.getHeight() - h);
                }
            });
            frame.getContentPane().add(newFrame);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    }
    class MainGameScreen extends JPanel {
        static final int ROWS = 13;
        static final int COLS = 27;

        public MainGameScreen() {
            setPreferredSize(new Dimension(864, 551));
            setLayout(new GridBagLayout());
            setBackground(Color.green);
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.fill = GridBagConstraints.BOTH;
            gbc.weightx = 1;
            gbc.weighty = 1;
            gbc.ipadx = 0; //Change to 64 to see undesired effects
            gbc.ipady = 0; //^
            for (int i=0;i<ROWS;i++) {
                for (int j=0;j<COLS;j++) {
                    gbc.gridx = j;
                    gbc.gridy = i;
                    add(new ImagePanel(), gbc);
                }
            }
        }
    }

    class ImagePanel extends JComponent {
        private int r,g,b;
        public ImagePanel() {
            Random generator = new Random();
            r = generator.nextInt(100)+1;
            g = generator.nextInt(100)+1;
            b = generator.nextInt(100)+1;
        }
        @Override
        public void paintComponent(Graphics gr) {
            super.paintComponent(gr);
            gr.setColor(new Color(r,g,b));
            gr.fillRect(0, 0, getWidth(), getHeight());
        }
}

关于java - GridBagLayout无法在组件之间正确分配尺寸,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13897036/

10-12 06:52