使用JPanels java的网格布局

时间:2016-11-19 14:31:00

标签: java swing panel

我正在尝试用Java创建一个类似于棋盘游戏的程序。我有gameTiles,目前只有一种颜色,因为我试图让布局正确。我希望瓷砖出现在窗口宽度的一半左右,并延伸到底部,可能是9x9或11x11不同瓷砖的任何地方。我试图使用网格布局来使它们靠近在一起,不一定触摸但足够接近看起来像棋盘游戏。然而,无论我尝试什么,瓷砖都是相距太远的空间,并在我调整窗口大小时改变形状。我一直在使用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的属性,我现在正在尝试的是将瓷砖彼此相邻。 这就是我得到的:

http://i.imgur.com/nXfrYSU.png

2 个答案:

答案 0 :(得分:2)

添加像网格一样的图块。 tileSize变量非常棒。我们假设图像/图块是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的大小。 请记住,在整个屏幕上循环,你想要一半,但它很容易配置。

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

每个GameTile也没有JPanel。而是将其保留在主绘图类中,并使用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);
    }

因此,我们不是在每个gameTile的JFrame中添加JPanel,而是在指定的坐标处绘制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课程中,删除extends JPanel。并将paintComponent重命名为draw或类似内容。

答案 1 :(得分:1)

  

然而,无论我尝试什么,瓷砖都是相距太远的空间,当我调整窗口大小时会改变形状

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

因此,解决方案是将您的瓷砖面板包装到另一个面板中,该面板将遵循瓷砖的首选尺寸。因此,不要设置框架的布局,设置包含图块的面板的布局:

类似的东西:

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);

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