Java I';我试图制作一个笑脸GUI,但在我的JButtons上总是给我一个空指针异常(NPE)

Java I';我试图制作一个笑脸GUI,但在我的JButtons上总是给我一个空指针异常(NPE),java,class,jpanel,jbutton,paintcomponent,Java,Class,Jpanel,Jbutton,Paintcomponent,我需要建立一个标准的笑脸图形用户界面,在那里你可以眨眼,眨眼,微笑,皱眉头。我需要使用三个独立的类来完成这项工作:一个绘制笑脸的类,一个包含所有按钮和控制笑脸的ActionListener的类,以及一个包含小程序的类 在button类中,我的按钮上不断出现NPE。我不明白为什么。请对我放轻松点,我是Java新手 这是我的控件类: public class SmileyControls extends JPanel implements ActionListener { Smiley s

我需要建立一个标准的笑脸图形用户界面,在那里你可以眨眼,眨眼,微笑,皱眉头。我需要使用三个独立的类来完成这项工作:一个绘制笑脸的类,一个包含所有按钮和控制笑脸的ActionListener的类,以及一个包含小程序的类

在button类中,我的按钮上不断出现NPE。我不明白为什么。请对我放轻松点,我是Java新手

这是我的控件类:

public class SmileyControls extends JPanel implements ActionListener {

    Smiley smiley;

    JPanel controlPanel, eyePanel;
    JButton open, wink, shut; // make these an animation???? see loop chapter in text

    public SmileyControls(Smiley smileControl) {

        smiley = smileControl;
        controlLayout();
    }

    public void controlLayout() {

        eyePanel = new JPanel(new FlowLayout());
        open = new JButton("Open");
        wink = new JButton("Wink");
        shut = new JButton("Shut");

        open.addActionListener(this);
        wink.addActionListener(this);
        shut.addActionListener(this);

        eyePanel.add(open);
        eyePanel.add(wink);
        eyePanel.add(shut);
        add(eyePanel);
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        if(e.getSource()==open){
            smiley.setEyeCondition(0);  // this calls the method setEyeCondition() from the smiley class that I created. I'm getting my NPE's here
        }
        if(e.getSource()==wink){
            smiley.setEyeCondition(1);  // and here
        }
        if(e.getSource()==shut){
            smiley.setEyeCondition(2);  // and here
        }
    }
}
这是我的笑脸课:

public class Smiley extends JPanel {

    int locX, locY, height, width;
    Color moleColor;
    int eyeCondition;
    Graphics2D g2d;

    public Smiley(int x, int y, int w, int h) {

        locX = x;
        locY = y + 100; // needed to add 100 pixels to make room for hair
        height = h;
        width = w;

        moleColor = new Color(84,60,37);
        eyeCondition = 0;
    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);

        g2d= (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

        setHair();
        setFace();
        setEyes();  // these methods paint the face
        setMole();
        setMouth();
    }

    // CONTROL METHODS

    public void setEyeCondition(int eye) {

        // the int values here are taken from the smileyControls class
        // I think they'd repaint my applet if it weren't for the NPE's

        if(eye == 0) {
            // draw eyes open
            g2d.fillOval(locX+width/5, locY+height/5,width/5, height/5); // left eye
            g2d.fillOval(locX+3*width/5, locY+height/5, width/5, height/5); // right eye
            repaint();
        } else if(eye == 1) {
            // draw wink
            g2d.fillRect(locX+width/5, locY+height/5,width/2, height/20); // left eye winking
            g2d.fillOval(locX+3*width/5, locY+height/5, width/5, height/5); // right eye open
            repaint();
        } else if(eye == 2) {
            // draw blink
            g2d.fillRect(locX+width/5, locY+height/5,width/2, height/20); // left eye blinking
            g2d.fillRect(locX+3*width/5, locY+height/5,width/2, height/20); // right eye blinking
            repaint();
        }
    }

    public void setEyes() { // this method paints the original eyes

        g2d.setColor(Color.black);
        g2d.fillOval(locX+width/5, locY+height/5,width/5, height/5); // left eye
        g2d.fillOval(locX+3*width/5, locY+height/5, width/5, height/5); // right eye
    }

}
这是我的小程序:

public class SmileyApplet extends JApplet {

    Smiley smiley1;
    SmileyControls control1;

    JPanel container, smileyAndControls1, smileyAndControls2, smileyAndControls3;

    BorderLayout border;

    public void init() {

        border = new BorderLayout();
        setLayout(border);

        setUpContainer();

    }

    public void setUpContainer() {

        container = new JPanel(new FlowLayout());
        smileyAndControls1 = new JPanel(new FlowLayout());

        setUpControl();
        setUpSmiley();

        smiley1.setPreferredSize(new Dimension(450, 600));

        smileyAndControls1.add(control1);
        smileyAndControls1.add(smiley1);

        container.add(smileyAndControls1);  // add more controls to master container here

        add(container, BorderLayout.CENTER);
    }

    public void setUpSmiley() {

        smiley1 = new Smiley(0, 0, 400, 400);
        add(smiley1);
    }

    public void setUpControl() {

        control1 = new SmileyControls(smiley1);
    }

}

首先调用
setUpControl()
,在那里创建
SmileyControls
并将
smiley1
传递给它(当时为
null
)。 然后调用
setUpSmiley()
,创建
Smiley
的实例


因此,在调用
setUpControl()
之前,您可能只需调用
setUpSmiley()
,您的问题就应该得到解决。

尝试更改这些行的顺序,因为您在
smiley1
变量获得其值之前使用它:

    setUpControl(); // This uses smiley1
    setUpSmiley();  // This instantiates smiley1
编辑 应将图形移动到
paint*()
方法,或直接从这些方法调用的方法


也就是说,您的
seteyecodition()
方法应该在smiley上设置一个属性,并且图形应该进入您的
setEyes()
方法。

在控件类的actionPerformed方法中抛出的
异常
具体在哪里。您必须向下滚动,行被注释。不要维护对您未创建的
图形
上下文的引用,而是将提供给您的引用传递给需要使用它的方法,这些方法摆脱了NPE,谢谢!!但现在我的纽扣无法重新粉刷眼睛。我在想,这是因为我在用一种非绘画成分的方法绘画?那就摆脱了NPE,谢谢!!但现在我的纽扣无法重新粉刷眼睛。我在想,这是因为我在用一种不是paintComponent的方法作画?