I am trying to write the code for a face that winks. My code doesn't give me any errors however when I try to run it the window comes up as a blank window. It does have the corredt title but no face is drawn in it and I'm not sure why.

import java.awt.Dimension;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JFrame;

class Face{
	private boolean wink;
	private final int x, y;
	private final int faceRadius;
	private final Color faceColor = Color.YELLOW;
	private final int faceDiameter, faceLeft, faceTop;
	private final int mouthWidth, mouthHeight, mouthLeft, mouthTop;
	private final int eyeDiameter, eyeTop, leftEyeLeft, rightEyeLeft;
	public static final int NOSE_WIDTH = 100;
	public static final int NOSE_HEIGHT = 50;
	public static final int X_NOSE = 150;//Center of nose will be at 200
	public static final int Y_NOSE = 130;
	public static final int NOSE_START_ANGLE = 90;
	public static final int NOSE_DEGREES_SHOWN = 170;
	

	private static final Color EYE_COLOR = Color.BLACK;
	private static final Color MOUTH_COLOR = Color.BLACK;
	

	public Face(){
		this(200, 100, 75, Color.YELLOW);
	}

	public Face(int centerX, int centerY, int radius, Color color) {
		wink = true;
		x = centerX;
		y = centerY;
		faceRadius = radius;
		faceDiameter = 2 * faceRadius;

		faceLeft = x - faceRadius;
		faceTop = y - faceRadius;

		mouthWidth = (int)(0.4 * faceDiameter);
		mouthHeight = mouthWidth / 4;
		mouthLeft = x - mouthWidth/2;
		mouthTop = y + 2 * mouthHeight;
		int mouthRight = mouthLeft + mouthWidth - 1;

		int eyeRadius = (int)(0.15 * faceRadius);
		eyeDiameter = 2 * eyeRadius;

		eyeTop = y - (faceRadius - 2 * mouthHeight) / 3;
		leftEyeLeft = mouthLeft - eyeRadius;
		rightEyeLeft = mouthRight - eyeRadius;

	}

	public void wink(){
		wink = true;
	}

	public void normal(){
		wink = false;
	}

	public void paintFace(Graphics g){
		//Draw face
		g.setColor(faceColor);
		g.fillOval(faceLeft, faceTop, faceDiameter, faceDiameter);

		//Draw Eyes
		g.setColor(EYE_COLOR);
		g.fillOval(leftEyeLeft, eyeTop, eyeDiameter, eyeDiameter);
		g.fillOval(rightEyeLeft, eyeTop, eyeDiameter, eyeDiameter);

		//Draw mouth
		g.setColor(MOUTH_COLOR);
		int ovalTop = mouthTop - mouthHeight;
		g.fillOval(mouthLeft, ovalTop, mouthWidth,2 * mouthHeight);
		
		//Draw nose:
		g.setColor(Color.BLACK);
		g.drawArc(X_NOSE, Y_NOSE, NOSE_WIDTH, NOSE_HEIGHT, NOSE_START_ANGLE, NOSE_DEGREES_SHOWN);

		g.setColor(faceColor);
		if(wink){
			g.fillOval(rightEyeLeft, eyeTop, eyeDiameter, eyeDiameter);
		}else{
			g.fillOval(rightEyeLeft, eyeTop, eyeDiameter, eyeDiameter);
		}
	}
}
class FacePanel extends JPanel{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public static final int PANEL_WIDTH = 400;
	public static final int PANEL_HEIGHT = 550;
	public static final int FACE_X = PANEL_WIDTH / 2;
	public static final int FACE_Y = PANEL_HEIGHT / 2;
	public static final int FACE_RADIUS = PANEL_WIDTH / 4;
	public static final Color FACE_COLOR = Color.YELLOW;

	private final Face aFace;

	public FacePanel(){
		aFace = new Face(FACE_X, FACE_Y, FACE_RADIUS, FACE_COLOR);
		setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
	}

	public void paintComponent(Graphics g){
		aFace.paintFace(g);
	}

	public void setWink(boolean wink){
		if(wink){
			aFace.wink();
		}else{
			aFace.normal();
		}
		repaint();
	}
}
class faceAndButtonPanel extends JPanel{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private final FacePanel facePanel;
	private final JPanel buttonPanel;
	private static final boolean WINK = true, NORMAL = false;

	public faceAndButtonPanel(){
		facePanel = new FacePanel();

		buttonPanel = new JPanel();
		ButtonListener listener = new ButtonListener();

		JButton winkButton = new JButton("Wink");
		winkButton.setActionCommand("wink-button");
		winkButton.addActionListener(listener);
		buttonPanel.add(winkButton);

		JButton normalButton = new JButton("Normal");
		normalButton.setActionCommand("normal-button");
		normalButton.addActionListener(listener);
		buttonPanel.add(normalButton);

	}

	private	class ButtonListener implements ActionListener{

		public void actionPerformed(ActionEvent event){
			if("wink-button".equals(event.getActionCommand())){
				facePanel.setWink(WINK);
			}else{
				facePanel.setWink(NORMAL);
			}
		}
	}
}


public class FaceDriver {

	public static void main (String[] args){
		JFrame window = new JFrame();
		window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		window.setTitle("Winking Face");

		faceAndButtonPanel panel = new faceAndButtonPanel();
		window.add(panel);
		window.pack();
		window.setVisible(true);
	}
}

Recommended Answers

All 2 Replies

there are lots of (newbee)mistakes, to avoid long debate..., better will be compare that with runnable code (with processes mistakes, maybe my helicopter view)

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;

public class Face {

    private final FaceModel model;//The model holds application data and defines the needed behaviour:

    public Face() {
        FaceView view = new FaceView(this);
        model = new FaceModel(); //The view observes the model (so it can react when the model data changes):

        model.addObserver(view);
        view.setVisible(true);
    }

    public void changeFace() {//This method is a controller function (called by the view to inform the model about user actions):
        model.setWink(!model.isWink());
    }

    public static void main(final String[] args) {
        Runnable gui = new Runnable() {

            @Override
            public void run() {
                Face face = new Face();
            }
        };
        SwingUtilities.invokeLater(gui);//GUI must start on EventDispatchThread:
    }
}

class FaceModel extends Observable {

    private boolean wink;

    public FaceModel() {
    }

    public boolean isWink() {
        return wink;
    }

    public void setWink(final boolean wink) {
        this.wink = wink;
        setChanged();//model has been changed
        notifyObservers(this);//notify the view
    }
}

class FaceView extends JFrame implements Observer {

    private static final long serialVersionUID = 1L;
    private Face face;//controller
    private JPanel buttonPanel;
    private FacePanel myFace;

    public FaceView(final Face face) {
        super("Face");
        this.face = face;
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        init();
        pack();
        setLocationRelativeTo(null);
    }

    private void init() {
        myFace = new FacePanel();
        buttonPanel = new JPanel();
        getContentPane().add(myFace, BorderLayout.CENTER);//Default layout of JFrame is BorderLayout:
        JButton winkButton = new JButton("Wink ;)");
        winkButton.setBackground(Color.GRAY);
        winkButton.setFocusable(false);
        buttonPanel.add(winkButton);//Default layout of JPanel is FlowLayout (with default alignment = CENTER):
        getContentPane().add(buttonPanel, BorderLayout.SOUTH);
        winkButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(final ActionEvent event) {
                face.changeFace();//here we simply call the corresponding controller function:
            }
        });
    }

    //This method is invoked whenever the model changes.
    //See java.util.Observer#update(java.util.Observable, java.lang.Object)
    @Override
    public void update(final Observable arg0, final Object arg1) {
        FaceModel model = (FaceModel) arg1;
        myFace.change(model.isWink());//Change the display according to the model data:
    }
}

class FacePanel extends JPanel {

    private static final long serialVersionUID = 1L;
    private final int L_EYE_X = 175;
    private final int L_EYE_Y = 250;
    private final int L_EYE_WIDTH = 100;
    private final int L_EYE_HEIGHT = 50;
    private final int R_EYE_X = 325;
    private final int R_EYE_Y = 250;
    private final int R_EYE_Y_WINK = 275;
    private final int R_EYE_WIDTH = 100;
    private final int R_EYE_HEIGHT = 50;
    private final int R_EYE_HEIGHT_WINK = 10;
    private final int NOSE_X = 275;
    private final int NOSE_Y = 350;
    private final int NOSE_WIDTH = 50;
    private final int NOSE_HEIGHT = 50;
    private final int MOUTH_X = 200;
    private final int MOUTH_Y = 400;
    private final int MOUTH_WIDTH = 200;
    private final int MOUTH_HEIGHT = 100;
    private boolean wink;//controls the appearance of the face

    public FacePanel() {
        super();
        setBackground(Color.WHITE);//All layout managers use the preferred size to set the final component size:
        setPreferredSize(new Dimension(600, 700));
    }

    @Override
    public void paintComponent(final Graphics g) {
        super.paintComponent(g); //the Graphics is in fact a Graphics2D with more features:
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);//for smooth drawing
        g.drawOval(100, 150, 400, 400);
        g.fillOval(L_EYE_X, L_EYE_Y, L_EYE_WIDTH, L_EYE_HEIGHT);
        if (wink) {
            g.fillOval(R_EYE_X, R_EYE_Y_WINK, R_EYE_WIDTH, R_EYE_HEIGHT_WINK);
        } else {
            g.fillOval(R_EYE_X, R_EYE_Y, R_EYE_WIDTH, R_EYE_HEIGHT);
        }
        g.setColor(Color.RED);
        g.fillOval(NOSE_X, NOSE_Y, NOSE_WIDTH, NOSE_HEIGHT);
        g.setColor(Color.BLACK);
        g.drawArc(MOUTH_X, MOUTH_Y, MOUTH_WIDTH, MOUTH_HEIGHT, 180, 180);
    }

    public void change(final boolean wink) {
        this.wink = wink;
        repaint();
    }
}

Thank you! I can see the changes you made and it sort of makes sense.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.