简体   繁体   中英

java animation, making an object change color every 'x' seconds

hi there i was just wondering if someone could help me or give me some advice with timers, the problem i have got is that i need an object to change color every x seconds on click of a button 'flash' and stay a single color on click of a button 'steady' so far i have got my buttons to work i just cant seem to get the object to 'flash'(change color on its own). my code is below and works without problems.

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


/**
 * Created by joe on 26/03/15.
 */

    class Beacon extends JPanel {
    private boolean lightOn = true;

    private int x = 150;
    private int y = 90;
    private int ballSize = 55;

        public void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2 = (Graphics2D) g;
                if (lightOn){
                    g2.setColor(Color.BLACK);
                    g2.fillRect(172, 140, 12, 30);
                    g2.drawRect(172, 170, 11, 30);
                    g2.fillRect(172, 200, 12, 30);
                    g2.drawRect(172, 230, 11, 30);
                    g2.fillRect(172, 260, 12, 30);
                    g2.drawRect(172, 290, 11, 30);
                    g2.fillRect(172, 320, 12, 30);
                    g2.drawRect(172, 350, 11, 30);
                    g2.setColor(Color.ORANGE);
                    g2.fillOval(x, y, ballSize, ballSize);
                }
            else{
        g2.setColor(Color.BLACK);
        g2.fillRect(172, 140, 12, 30);
        g2.drawRect(172, 170, 11, 30);
        g2.fillRect(172, 200, 12, 30);
        g2.drawRect(172, 230, 11, 30);
        g2.fillRect(172, 260, 12, 30);
        g2.drawRect(172, 290, 11, 30);
        g2.fillRect(172, 320, 12, 30);
        g2.drawRect(172, 350, 11, 30);
        g2.setColor(Color.GRAY);
        g2.fillOval(x, y, ballSize, ballSize);
    }   }
    public void lightOn() { lightOn = true; }
    public void lightOff() { lightOn = false; }
}

    public class BeaconViewer extends JFrame
    {
        JButton Flash = new JButton("Flash");
        JButton Steady = new JButton("Steady");
        JPanel bPanel = new JPanel();
        Beacon bbPanel = new Beacon();



    public BeaconViewer()
    {
        bPanel.add(Flash);
        this.add(bPanel, BorderLayout.SOUTH);
        bPanel.add(Steady);
        this.add(bbPanel, BorderLayout.CENTER);
        Flash.addActionListener(new FlashListener());
        Steady.addActionListener(new SteadyListener());
    }

        class FlashListener implements ActionListener {

            public void actionPerformed(ActionEvent e) {
                bbPanel.lightOff();
                repaint();

            }

        }

        class SteadyListener implements ActionListener {

            public void actionPerformed(ActionEvent a) {
                bbPanel.lightOn();
                repaint();
            }

        }

        public static void main(String[] args) {
        JFrame scFrame = new BeaconViewer();
        scFrame.setTitle("Belish Beacon");
        scFrame.setSize(300, 500);
        scFrame.setDefaultCloseOperation((JFrame.EXIT_ON_CLOSE));
        scFrame.setVisible(true); }}

What you'd like to do is use a swing timer and register it an AbstractAction or ActionListener which it will fire based on a delay parameter that you pass it.

For example, I may have...

...
Timer timer = new Timer(FRAME_DELAY, myActionListener);
timer.start();
...

where FRAME_DELAY is the number of milliseconds between event firings and myActionListener receives the notification of the action performed.

Once you have the timer you can adjust the delay, stop, and restart among other things. See Timer for better information.

Start by taking a look at How to use Swing Timers

First you need someway to tell if the Beacon is on or off, we achieve this by adding

public boolean isLighOff() {
    return !lightOn;
}

to the Beacon class.

Next, we need an instance of javax.swing.Timer

public class BeaconViewer extends JFrame {
    //...
    private Timer flashTimer;

    public BeaconViewer() {
        //...
        flashTimer = new Timer(1000, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (bbPanel.isLighOff()) {
                    bbPanel.lightOn();
                } else {
                    bbPanel.lightOff();
                }
                repaint();
            }
        });
        flashTimer.setInitialDelay(0);
    }

This is used to schedule a regular call back at the specified duration (1 second) which determines the current state of the Beacon and switches the state...The reason for using a Swing Timer like this, apart from simplicity, is because it's safe to modify the UI components from within the assigned ActionListener

Next, we need to start and top the Timer accordingly...

class FlashListener implements ActionListener {

    public void actionPerformed(ActionEvent e) {
        flashTimer.start();
    }

}

class SteadyListener implements ActionListener {

    public void actionPerformed(ActionEvent a) {
        if (flashTimer.isRunning()) {
            flashTimer.stop();
        }
        bbPanel.lightOn();
        repaint();
    }

}

This is very easy to accomplish, all you need to do is use System.currentTimeMillis() something like this

start = System.currentTimeMillis()
//stuff
finish = System.currentTimeMillis()
elapsed = finish - start

if the result is greater than 1,000 then a second has passed. You will probably want to put this timer in a separate thread depending on how you want to implement it in your program.

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