有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

用JPanelsJava实现swing网格布局

我正在尝试用Java创建一个类似于棋盘游戏的程序。我有游戏瓷砖,目前只有一种颜色,因为我试图得到正确的布局。我希望瓷砖显示在窗口宽度的一半左右,并延伸到底部,可能是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);
}
    }

这是游戏窗口。java文件。游戏片。到目前为止,我已经完成的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的属性,我现在尝试的就是让这些Tile彼此相邻。 这就是我得到的:

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


共 (2) 个答案

  1. # 1 楼答案

    要像网格一样添加平铺。有一个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"));移动到构造函数中,现在您正在为每个游戏块以每帧速率加载图像,这将导致性能下降

    也没有一个JPanel用于每个游戏块。相反,将其保留在主绘图类中,并使用ArrayList循环遍历所有游戏片

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

    因此,我们不是为每个游戏片向JFrame添加JPanel,而是在指定的坐标处绘制游戏片。祝你好运

    要在注释字段中回答您的问题:代码看起来与此类似

    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或类似的名称

  2. # 2 楼答案

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

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

    上述操作将导致平铺显示在垂直居中的框架右侧