因为在网上找了很多文章才搞懂这个问题,所以写下这个解决问题后的随笔希望能帮到更多的初学者,如有不对请大佬指正勿喷。
相信肯定有小伙伴代码是这样写的,导致报空指针的错误。
public class Test extends JFrame{
public Test() {
Graphics gr;
gr = getGraphics();
gr.fillOval(50, 50, 50, 50);
setTitle("画图");
setBounds(300, 300, 340, 240);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
这是因为画笔要在设定可使后才能获取,在setVisible(true);之前获取画笔是不能获取到画笔的。
通过调试可以发现gr的值为null,表示并未获取到Graphics对象。
那我们换一下位置,是不是就能显示图像了呢?
public Test() {
Graphics gr;
setTitle("画图");
setBounds(300, 300, 340, 240);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
gr = getGraphics();
gr.fillOval(50, 50, 50, 50);
}
我们将代码改成这样,然后运行,得到结果:
可以看到,并没有任何图像在上面,说明程序还是有问题,否则应该是有一个半径为50的圆在图上的。我们现在可以假设两种情况:一、画笔获取到了,但是获取错了,图像画错地方了。二、程序画了,但是又被覆盖了。
我们通过调试得到如下结果:
可以看到画笔gr已经获取到了,图形也画上去了,那就证明程序逻辑是没有问题的,第一种情况可以否定了。那为什么程序正常运行时不报错也没有图形呢?
我们首先了解一下paint函数,这是JFrame和JPanel都有的一个函数,可以手动重写,程序执行时自动调用。
可以看到,这里我们没有在构造函数里面获取画笔也没有再主函数里面调用paint方法,但是程序依旧画出了一个圆形。这是因为paint方法在构造对象后会自动调用,传入paint函数的参数Graphics g 是默认正在创建的对象的画笔。
基于以上知识,我们将代码改成如下情况再执行:
public Test() {
Graphics gr;
setTitle("画圆");
setBounds(300, 300, 340, 240);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
gr = getGraphics();
gr.fillRect(100, 100, 50, 50);
System.out.println("draw");
}
public void paint(Graphics g) {
System.out.println("paint");
g.fillOval(50, 50, 50, 50);
}
可以发现,先画了构造函数里面的图形,然后又调用了几遍paint函数,导致之前被画上去的图被覆盖了。所以假设二成立,程序是由于先画了矩形后又调用paint函数导致图形被覆盖。
那么因为paint函数导致覆盖可不可以用其他方式解决呢?比如写一个函数,创建对象后调用。
此时需要将Graphics变量定义为成员变量,以便其他函数调用,测试代码如下:
public class Test extends JFrame{
Graphics gr; //成员变量
public Test() {
setTitle("画圆");
setBounds(300, 300, 340, 240);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
gr = getGraphics();
}
public void paint(Graphics g) {
System.out.println("paint");
g.fillOval(50, 50, 50, 50);
}
public void Draw() {
System.out.println("Draw");
gr.setColor(Color.red);
gr.fillRect(100, 100, 50, 50);
}
public static void main(String[] args) {
Test p = new Test();
p.Draw();
}
}
测试结果为:
可以看见,函数画的图还是被覆盖了。
因为每次对窗口进行改变时,都会重新调用paint方法实时绘图,所以会导致图像覆盖。因此要想获取稳定的图像需要将绘图代码写在paint里面。
总结:一、如果Graphics对象是空指针,检查一下是否是由于没有在获取画笔之前设置可见模式(setVisible(true);)。二、画图的代码要写在重写的paint函数里面,写在构造函数或者其他函数里面都有被覆盖而无法显示的可能,(写在主函数里面偶尔不会被覆盖)如: