[英]JPanel displaying weird error when drawing image
我在棋盘游戏中遇到了一个奇怪的错误。 该板由带有GameTiles的2D数组组成,GameTiles是JPanel的子类。 当我有大小(600,500)时,一切都很好,但每当我改变它时,左上角会出现一个奇怪的错误。
错误图片(见左上角)
甚至更奇怪的是,当我创建一个新项目时,只是为了尝试它,它完美地工作。 这幅画的代码完全相同,我没有遇到任何错误。 可能是导致这个问题的其他因素吗?
问题固定
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
根据你的评论:
这就是问题所在,非常感谢您指出这一点。 我在棋盘上移动时使用坐标。 如果有一些方法可以做出这个答案那就太棒了
在GameTile.java
你做了:
public int getX() {
return x;
}
public int getY() {
return y;
}
有了这个,你实际上覆盖了JPanel
的getX
和getY
并返回了会影响Layout
的坐标。 通过添加@Override
注释可以看出这一点(注意不会抛出编译器错误,因此我们正确地覆盖了扩展类中的方法):
@Override
public int getX() {
return x;
}
@Override
public int getY() {
return y;
}
正如@Xeon所说,你不应该设置坐标, LayoutManager
会这样做。
解决方案:(加上额外内容)
删除那些getter或适当地重命名它们。
不要在JFrame
上调用setSize
,而是覆盖JPanel which is drawn to via
getPreferredSize
, JPanel which is drawn to via
Graphic s object and return the correct
JPanel which is drawn to via
s object and return the correct
Dimension s (in your case the image dimensions) and than call [
][4] on
JFrame` ][4] on
s (in your case the image dimensions) and than call [
pack() ][4] on
然后将其设置为可见但添加组件后。
您需要将对setLocationRelativeTo(...)
调用重新定位到pack()
。
最好使用JFrame.DISPOSE_ON_CLOSE
因此即使在GUI终止后, main(String[] args)
方法也可以继续执行。
也不要不必要地扩展JFrame
。
不要在GameTile
类中重复加载相同的图像而是加载图像一次并为GameTile
添加参数以接受BufferedImage
(我在使用因特网URL进行测试时想到了这一点,因为它为每个创建的GameTile
读取了一个新图像)
以下是进行必要更改的类:
Reversi.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");
}
});
}
}
GameBoard.java :
public class GameBoard extends JPanel {
private GameTile[][] gameBoard = new GameTile[8][8];
public GameBoard() {
initiateLayout();
}
private void initiateLayout() {
setLayout(new GridLayout(8, 8));
BufferedImage image = null;
try {
image = ImageIO.read(new URL("http://i.imgur.com/ejmCtui.png"));
} catch (IOException e) {
e.printStackTrace();
}
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
gameBoard[row][col] = new GameTile(image, 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();
}
}
}
}
GameTile.java:
public class GameTile extends JPanel {
private BufferedImage image;
private int x;
private int y;
public GameTile(BufferedImage image, int x, int y) {
this.image = image;
this.x = x;
this.y = y;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(image.getWidth(), image.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
}
}
GameFrame.java:
public class GameFrame {
private GameBoard gameBoard;
/**
* Creates a new frame.
*
* @param gameTitle the title of the frame
*/
public GameFrame(String gameTitle) {
JFrame frame = new JFrame(gameTitle);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
gameBoard = new GameBoard();
frame.add(gameBoard);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
会产生:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.