Java 个图形出现 NullPointerException
NullPointerException on Java graphics
我正在尝试实现一种方法来绘制网格的特定部分。为此,我覆盖了 paintComponent 方法:
public class Frame extends JPanel {
...
@Override
public void paintComponent( Graphics g ) {
super.paintComponent( g );
g.clearRect(0, 0, getWidth(), getHeight());
this.rectWidth = getWidth() / this.NUM_COLUMNS;
this.rectHeight = getHeight() / this.NUM_ROWS;
for (int i = 0; i < NUM_ROWS; i++) {
for (int j = 0; j < NUM_COLUMNS; j++) {
int x = i * this.rectWidth;
int y = j * this.rectHeight;
g.setColor( Color.WHITE );
g.fillRect( x, y, this.rectWidth, this.rectHeight );
}
}
}
}
这很好,但是,我想在这样的函数调用上绘制特定部分:
public void specificPaint( int coordinateX, int coordinateY, Color color ){
Graphics g = this.getGraphics();
int x = coordinateX * this.rectWidth;
int y = coordinateY * this.rectHeight;
g.setColor( color );
g.fillRect( x, y, this.rectWidth, this.rectWidth);
}
调用应该是这样的
// TESTING
this.modelMap.specificPaint( 40,40,Color.RED );
this.modelMap.specificPaint( 10,10,Color.RED );
this.modelMap.specificPaint( 20,25,Color.BLUE );
我遇到了 Graphics 对象的空指针错误,为什么我不能恢复并使用它?
有没有更好的方法?
从组件获取 Graphics 对象时切勿这样做:
Graphics g = this.getGraphics();
由此获得的 Graphics 对象将不会长期存在,这可能会导致 NPE(就像您得到的那样)或在重绘时不持久的图像。相反,在 paintComponent 方法中进行绘图。请注意,您可以调用 repaint(...)
并通过传入 Rectangle 参数指定要绘制的特定 Rectangle。
请注意,您可以在 BufferedImage 上调用 getGraphics()
并对其进行绘制,然后在您的 paintComponent 方法中绘制 BufferedImage 如果您想进行不移动的点绘制。
一个不相关的建议:避免调用您的 class Frame
,因为如果您不小心,这可能会导致与 java.awt.Frame
class 的名称冲突。
例如:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.*;
@SuppressWarnings("serial")
public class MyPanel extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private int cols;
private int rows;
private static final Color BG = Color.BLACK;
private static final int GAP = 1;
private BufferedImage img;
private int rectWidth;
private int rectHeight;
public MyPanel(int rows, int cols) {
this.cols = cols;
this.rows = rows;
img = createMyImage();
}
public void specificPaint(int coordinateX, int coordinateY, Color color) {
Graphics g = img.getGraphics(); // get img's Graphics object
int x = coordinateX * this.rectWidth + GAP;
int y = coordinateY * this.rectHeight + GAP;
g.setColor(color);
g.fillRect(x, y, rectWidth - 2 * GAP, rectWidth - 2 * GAP);
g.dispose();
repaint();
}
private BufferedImage createMyImage() {
img = new BufferedImage(PREF_W, PREF_H, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setBackground(BG);
g2.clearRect(0, 0, img.getWidth(), img.getHeight());
this.rectWidth = img.getWidth() / cols;
this.rectHeight = img.getHeight() / rows;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
int x = i * this.rectWidth + GAP;
int y = j * this.rectHeight + GAP;
g2.setColor(Color.WHITE);
g2.fillRect(x, y, this.rectWidth - 2 * GAP, this.rectHeight - 2 * GAP);
}
}
g2.dispose();
return img;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
// if you need to draw changing non-static images, do it here
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || img == null) {
return super.getPreferredSize();
}
int w = img.getWidth();
int h = img.getHeight();
return new Dimension(w, h);
}
private static void createAndShowGui() {
MyPanel modelMap = new MyPanel(50, 50);
JFrame frame = new JFrame("MyPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(modelMap);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
modelMap.specificPaint( 40,40,Color.RED );
modelMap.specificPaint( 10,10,Color.RED );
modelMap.specificPaint( 20,25,Color.BLUE );
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
改变
public void specificPaint(int coordinateX, int coordinateY, Color color)
到
public void specificPaint(int coordinateX, int coordinateY, Color color, Graphics g)
然后在您的 paintComponent
方法中调用 specificPaint
并使用您正在绘制的 Graphics
对象
请参阅 Hovercraft 的回答以了解有关为什么使用 this.getGraphics()
不起作用的更多详细信息
我正在尝试实现一种方法来绘制网格的特定部分。为此,我覆盖了 paintComponent 方法:
public class Frame extends JPanel {
...
@Override
public void paintComponent( Graphics g ) {
super.paintComponent( g );
g.clearRect(0, 0, getWidth(), getHeight());
this.rectWidth = getWidth() / this.NUM_COLUMNS;
this.rectHeight = getHeight() / this.NUM_ROWS;
for (int i = 0; i < NUM_ROWS; i++) {
for (int j = 0; j < NUM_COLUMNS; j++) {
int x = i * this.rectWidth;
int y = j * this.rectHeight;
g.setColor( Color.WHITE );
g.fillRect( x, y, this.rectWidth, this.rectHeight );
}
}
}
}
这很好,但是,我想在这样的函数调用上绘制特定部分:
public void specificPaint( int coordinateX, int coordinateY, Color color ){
Graphics g = this.getGraphics();
int x = coordinateX * this.rectWidth;
int y = coordinateY * this.rectHeight;
g.setColor( color );
g.fillRect( x, y, this.rectWidth, this.rectWidth);
}
调用应该是这样的
// TESTING
this.modelMap.specificPaint( 40,40,Color.RED );
this.modelMap.specificPaint( 10,10,Color.RED );
this.modelMap.specificPaint( 20,25,Color.BLUE );
我遇到了 Graphics 对象的空指针错误,为什么我不能恢复并使用它?
有没有更好的方法?
从组件获取 Graphics 对象时切勿这样做:
Graphics g = this.getGraphics();
由此获得的 Graphics 对象将不会长期存在,这可能会导致 NPE(就像您得到的那样)或在重绘时不持久的图像。相反,在 paintComponent 方法中进行绘图。请注意,您可以调用 repaint(...)
并通过传入 Rectangle 参数指定要绘制的特定 Rectangle。
请注意,您可以在 BufferedImage 上调用 getGraphics()
并对其进行绘制,然后在您的 paintComponent 方法中绘制 BufferedImage 如果您想进行不移动的点绘制。
一个不相关的建议:避免调用您的 class Frame
,因为如果您不小心,这可能会导致与 java.awt.Frame
class 的名称冲突。
例如:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.*;
@SuppressWarnings("serial")
public class MyPanel extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private int cols;
private int rows;
private static final Color BG = Color.BLACK;
private static final int GAP = 1;
private BufferedImage img;
private int rectWidth;
private int rectHeight;
public MyPanel(int rows, int cols) {
this.cols = cols;
this.rows = rows;
img = createMyImage();
}
public void specificPaint(int coordinateX, int coordinateY, Color color) {
Graphics g = img.getGraphics(); // get img's Graphics object
int x = coordinateX * this.rectWidth + GAP;
int y = coordinateY * this.rectHeight + GAP;
g.setColor(color);
g.fillRect(x, y, rectWidth - 2 * GAP, rectWidth - 2 * GAP);
g.dispose();
repaint();
}
private BufferedImage createMyImage() {
img = new BufferedImage(PREF_W, PREF_H, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setBackground(BG);
g2.clearRect(0, 0, img.getWidth(), img.getHeight());
this.rectWidth = img.getWidth() / cols;
this.rectHeight = img.getHeight() / rows;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
int x = i * this.rectWidth + GAP;
int y = j * this.rectHeight + GAP;
g2.setColor(Color.WHITE);
g2.fillRect(x, y, this.rectWidth - 2 * GAP, this.rectHeight - 2 * GAP);
}
}
g2.dispose();
return img;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
// if you need to draw changing non-static images, do it here
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || img == null) {
return super.getPreferredSize();
}
int w = img.getWidth();
int h = img.getHeight();
return new Dimension(w, h);
}
private static void createAndShowGui() {
MyPanel modelMap = new MyPanel(50, 50);
JFrame frame = new JFrame("MyPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(modelMap);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
modelMap.specificPaint( 40,40,Color.RED );
modelMap.specificPaint( 10,10,Color.RED );
modelMap.specificPaint( 20,25,Color.BLUE );
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
改变
public void specificPaint(int coordinateX, int coordinateY, Color color)
到
public void specificPaint(int coordinateX, int coordinateY, Color color, Graphics g)
然后在您的 paintComponent
方法中调用 specificPaint
并使用您正在绘制的 Graphics
对象
请参阅 Hovercraft 的回答以了解有关为什么使用 this.getGraphics()
不起作用的更多详细信息