使用 JPanels 的网格布局 java

grid layout with JPanels java

我正在尝试在 Java 中创建一个有点像棋盘游戏的程序。我有 gameTiles,目前只有一种颜色,因为我试图使布局正确。我希望瓷砖出现在 window 宽度的一半左右并延伸到底部,可能是 9x9 或 11x11 不同瓷砖的任何地方。我尝试使用网格布局让它们靠近在一起,不一定接触但足够靠近看起来像棋盘游戏。但是,无论我尝试什么,瓷砖都相距 space 很远,并且在我调整 window 大小时改变形状。我一直在使用 GridLayout 管理器来尝试实现这一点。这是我的代码。

    import java.awt.GridLayout;
    import javax.swing.JFrame;
    public class GameWindow extends JFrame {

public GameWindow(String title){
    super(title);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(1200,400);
}

/**
 * @param args
 */
public static void main(String[] args) {
    GameWindow gameWindow = new GameWindow("Game");
    gameWindow.setLayout(new GridLayout(0,2));
    GameTile greenTile = new GameTile(0,true,0,10);
    GameTile greenTile2 = new GameTile(0,true,0,10);
    gameWindow.add(greenTile);
    gameWindow.add(greenTile2);
    gameWindow.setVisible(true);
}
    }

这是 GameWindow.java 文件。目前我的GameTile.java(主要是还没做完只是为了测试)如下:

    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Image;
    import java.io.File;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    import javax.swing.JPanel;
    /**
    * @author Zachary Parks
    *
    */
    public class GameTile extends JPanel {
    private Color color;
    private Color[] colors = {Color.BLUE, Color.YELLOW, Color.BLACK};
    private int score, multiplier,initialX,initialY;
    private boolean positiveEffect;

    public GameTile(int colorTile, boolean effect, int initX, int initY){
    color = colors[colorTile];
    score = getScore(color);
    multiplier = getMultiplier(color);
    positiveEffect = effect;
    initialX = initX;
    initialY = initY;
    }
    protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Image image = null;
    try {
        image = ImageIO.read(new File("greentile.png"));
    } catch (IOException e) {
        e.printStackTrace();
    }
     g.drawImage(image,initialX,initialY,this);
    }

    private int getMultiplier(Color color2) {
    return 0;
    }

    private int getScore(Color color2) {
    return 0;
    }
    /**
    * Method that returns the data from the tile in 
    * array of int. 0 index = added score, 1 index = tile effect score
    * @return
    */
    public int[] getData() {
    int [] scoreData = null;
    scoreData[0] = score*multiplier;
    return null;    
    }
    }

很多代码仍在进行中,例如 GameTile 的属性,我目前正在尝试的只是让瓷砖彼此相邻。 这就是我得到的:

像网格一样添加图块。拥有一个 tileSize 变量真是太好了。假设 image/tile 是 32 像素。

public static final tileSize = 32;

有了这个,我们现在可以使用 for 循环添加图块:

for(int x = 0; x < SCREEN_WIDTH / GameTile.tileSize; x++) { // loop through as many tiles fit the x-axis.
    for(int y = 0; y < SCREEN_HEIGHT / GameTile.tileSize; y++) { // do the same with y-axis
        GameTile greenTile = new GameTile(0,true, x * GameTile.tileSize , y * GameTile.tileSize);
        gameWindow.add(greenTile);
     }
}

SCREEN_WIDTHSCREEN_HEIGHT 是 JFrame 的大小。 请记住,这会循环遍历整个屏幕,您想要一半,但它很容易配置。

下次请格式化您的代码(tab in),这样更容易阅读和帮助您。 我强烈建议将 image = ImageIO.read(new File("greentile.png")); 移动到构造函数中,现在您正在为每个 gameTile 的每个帧速率加载图像,这将导致性能下降。

也不是每个 GameTile 都有一个 JPanel。而是将其保留在主绘图中 class 并使用 ArrayList

遍历所有 GameTiles
public static ArrayList<GameTile> gameTiles = new ArrayList<GameTile>();

protected void paintComponent(Graphics g) {
    for(int i = 0; i < gameTiles.size(); i++) {
        gameTiles.get(i).draw(g);
    }

因此,我们不是将 JPanel 添加到每个 gameTile 的 JFrame,而是在指定坐标处绘制 gameTiles。祝你好运!

在评论区回答你的问题:代码将类似于此

public class GameWindow extends JPanel {

    public static ArrayList<GameTile> gameTiles = new ArrayList<GameTile>();

    public static void main(String[] args) {
        new GameWindow();
    }

    public GameWindow() {

        JFrame frame = new JFrame();    
        frame.setSize(300, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(this);
        frame.setVisible(true);

        // add all the tiles (I just use x and y as parameters here)
        gameTiles.add(new GameTile(10, 10));
        gameTiles.add(new GameTile(50, 10));

    }

    public void paintComponent(Graphics g) {

        for(int i = 0; i < gameTiles.size(); i++) {
            gameTiles.get(i).draw(g);
        }

    }

}

然后在您的 GameTile class 中,删除 extends JPanel。并将 paintComponent 重命名为 draw 或类似名称。

However, no matter what I try, the tiles are space so far apart, and change shape when I resize window

GridLayout 扩展每个单元格以填充组件可用的 space。如果您只有两个单元格,每个单元格将占据框架宽度的一半。

因此,解决方案是将您的拼贴面板包裹到另一个符合拼贴首选尺寸的面板中。所以不要设置框架的布局,设置包含图块的面板的布局:

类似于:

JPanel tilePanel = new JPane( new GridLayout(0, 2, 5, 5) );
tilePanel.add( new GameTile(...) );
tilePanel.add( new GameTile(...) );

JPanel wrapper = new JPanel( new GridBagLayout() ); 
wrapper.add(tilePanel, new GridBagConstraints() );

frame.add(wrapper, BorderLayout.CENTER );

以上代码将使图块在框架中居中。

frame.add(wrapper, BorderLayout.LINE_END);

以上将导致图块显示在垂直居中的框架右侧。