JPanel在绘制图像时显示奇怪的错误

时间:2013-01-31 18:55:45

标签: java swing jpanel paintcomponent grid-layout

我在棋盘游戏中遇到了一个奇怪的错误。该板由带有GameTiles的2D数组组成,GameTiles是JPanel的子类。当我有大小(600,500)时,一切都很好,但每当我改变它时,左上角会出现一个奇怪的错误。

错误图片(请参阅左上角) Board error

让我更奇怪的是,当我创建一个新项目时,只是为了尝试它,它运作得很好。这幅画的代码完全相同,我没有遇到任何错误。可能是造成这个问题的其他因素吗?

问题解决

Anser:我不小心覆盖了JPanel的getX和getY方法。我改变了它们的名字,现在它完美无缺。

Reversi.java

package org.reversi;

import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import org.reversi.gui.GameFrame;

public class Reversi {
public static void main(String[] args) {
    try {
                 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (UnsupportedLookAndFeelException e) {
        e.printStackTrace();
    }

    java.awt.EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            GameFrame frame = new GameFrame("Reversi");
            frame.setSize(600,500);
            frame.setLocationRelativeTo(null);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
        }
    });
}
}

GameBoard.java

package org.reversi.gui;

import java.awt.Graphics;
import java.awt.GridLayout;

import javax.swing.JPanel;

public class GameBoard extends JPanel{
private GameTile[][] gameBoard = new GameTile[8][8];

public GameBoard() {
    initiateLayout();
}

private void initiateLayout() {
    setLayout(new GridLayout(8, 8));

    for(int row = 0 ; row < 8 ; row++) {
        for(int col = 0 ; col < 8 ; col++) {
            gameBoard[row][col] = new GameTile(col,row);
            add(gameBoard[row][col]);
        }
    }
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    for(int row = 0 ; row < 8 ; row++) 
        for(int col = 0 ; col < 8 ; col++)              
            gameBoard[row][col].repaint();
}
}

GameFrame.java

package org.reversi.gui;

import javax.swing.JFrame;

public class GameFrame extends JFrame {
private GameBoard gameBoard;

/**
 * Creates a new frame.
 * @param gameTitle the title of the frame
 */
public GameFrame(String gameTitle) {
    setTitle(gameTitle);
    gameBoard = new GameBoard();
    add(gameBoard);
}
}

GameTile.java

package org.reversi.gui;

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class GameTile extends JPanel {
private BufferedImage image;
private int x;
private int y;

public GameTile(int x, int y) {
    this.x = x;
    this.y = y;
    try {
        this.image = ImageIO.read(new File("tile.png"));
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
}

public int getX() {
    return x;
}

public int getY() {
    return y;
}
}

链接到图片(应该命名为tile.png):http://i.imgur.com/ejmCtui.png

1 个答案:

答案 0 :(得分:3)

根据你的评论:

  

这就是问题所在,非常感谢您指出这一点。我   在棋盘上移动时使用坐标。如果有的话   如何做出这个答案会很棒

GameTile.java你做过:

public int getX() {
    return x;
}

public int getY() {
    return y;
}

通过此操作,您实际上会覆盖JPanelgetXgetY以及返回会影响Layout的坐标。通过添加@Override annotation可以看出这一点(注意不会抛出编译器错误,因此我们正确地覆盖了扩展类中的方法):

@Override
public int getX() {
    return x;
}

@Override
public int getY() {
    return y;
}

正如@Xeon所说,你不应该设置坐标LayoutManager会这样做。

解决方案:(加上额外内容)

  • 删除 getters 或正确重命名。

  • 请勿在{{1​​}}上致电setSize,而是覆盖JFrame图片getPreferredSize尺寸JPanel which is drawn to via pack(){{1}的s object and return the correct JFrame`在设置之前可见但在添加组件之后。

  • 您需要将s (in your case the image dimensions) and than call [之后的来电重新定位到][4] on之后。

  • 最好使用setLocationRelativeTo(...),因此即使在GUI终止后,pack()方法也可以继续执行。

  • 也不要不必要地延长JFrame.DISPOSE_ON_CLOSE

  • 请勿在{{1​​}}课程中反复加载相同的图片,而是加载图片一次并为main(String[] args)添加参数以接受JFrame(我在测试时使用了这一点因为它为每个创建的GameTile

  • 读取了一个新图像,所以它永远都是因特网URL

以下是进行必要更改的类:

<强> Reversi.java:

GameTile

<强> GameBoard.java

BufferedImage

<强> GameTile.java:

GameTile

<强> GameFrame.java:

public class Reversi {

    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }

        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new GameFrame("Reversi");
            }
        });
    }
}

会产生:

enter image description here