简体   繁体   中英

I have to draw a smiley face and make its left eye blink using Graphics and Timer, but it doesn't blink

I start the timer and call paintRect to redraw the eye and create the blink effect but it's not working. I call paintEye to draw the left eye again but with a yellow color.

I'm still trying to learn ActionListener works, so I'm not sure if I'm getting it right, which doesn't look like anyway.

import javax.swing.JPanel;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;

public class Content extends JPanel {

    public Content() {
    }

    @Override
    public void paintComponent(Graphics g) {

        //face
        g.setColor(Color.yellow);
        g.fillOval(10, 10, 200, 200);

        //eyes
        g.setColor(Color.black);
        g.fillOval(55, 65, 30, 30);
        g.fillOval(135, 65, 30, 30);

        //mouth
        g.setColor(Color.black);
        g.fillOval(50, 110, 120, 60);

        //touchUp
        g.setColor(Color.YELLOW);
        g.fillRect(50, 110, 120, 30);
        g.fillOval(50, 120, 120, 40);

        time.start();
        paintEye(super.getComponentGraphics(g));

        //eyesAgain
        g.setColor(Color.black);
        g.fillOval(55, 65, 30, 30);
    }

    public void paintEye(Graphics grphcs) {

        grphcs.setColor(Color.yellow);
        grphcs.fillOval(55, 65, 30, 30);
    }

    Timer time = new Timer(100, new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {


            repaint();
        }
    });

}

You've problems (as noted within comments)

  • Your Timer's ActionListener should change the state of an instance field, say a boolean called blink . I'd simply toggle its value: blink = !blink; , and then call repaint()
  • Your paintComponent should use the value of this boolean to decide what to paint, an open or closed eye
  • NEVER start or stop the Timer within the paintComponent method, but rather do so elsewhere such as in the constructor. The painting methods are for painting and painting only since you don't have full control over when or even if it is called, and you really only need to call start() on the Timer once, at the beginning of the program.
  • Your paintComponent method must call its super's method, first thing to clear out any "dirty" pixels -- eg, the closed eye or the open eye images:

@Override 
protected void paintComponent(Graphics g) {
    super.paintComponent(g); // ***** here

    // .... rest of the code goes below

    if (blink) {
        // ....
    } else {
        // ....
    }
}

eg, a simple toggle program

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.*;

public class Foo01 extends JPanel {
    private static final int PREF_W = 600;
    private static final int PREF_H = PREF_W;
    private static final Color COLOR_1 = Color.RED;
    private static final Color COLOR_2 = Color.BLUE;
    private static final int TIMER_DELAY = 100;
    private static final int RECT_X = 100;
    private static final int RECT_W = 400;
    private boolean blink = false;

    public Foo01() {
        setPreferredSize(new Dimension(PREF_W, PREF_H));
        new Timer(TIMER_DELAY, e -> {
            blink = !blink;
            repaint();
        }).start();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (blink) {
            g.setColor(COLOR_1);
        } else {
            g.setColor(COLOR_2);
        }
        g.fillRect(RECT_X, RECT_X, RECT_W, RECT_W);
    }

    private static void createAndShowGui() {
        Foo01 mainPanel = new Foo01();

        JFrame frame = new JFrame("Foo01");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM