0

我需要一个简单的动画任务帮助。它如下。

我在 a 上有两个停车灯,JPanel目的是让他们两个有不同的时间间隔,即灯在不同的时间循环。

如果我一次只有一盏灯,一切都很好。我对此比较陌生,但我相信我知道这个问题。

在本文下的代码中,我this多次使用。我相信我的问题出现在public void cycle()它刚才所说的方法中this.repaint();我有一种感觉,面板在两个不同的时间段被重新粉刷,它给了我一个有点随机的光线变化,而不是一个很好的循环。

JPanel有没有一种方法可以使用更具体的重绘方法(可能是单个灯具周围的边界框)将这两个组件放在同一位置,或者创建单独的面板是一个更好的选择(如果是这样的话,会有一点帮助,因为我了解基本布局,但以前从未使用过它们)。

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

public class DrawingPanel extends JPanel implements Lighter
{
    // instance variables 
    private final int INTERVAL1 = 2000;
    private final int INTERVAL2 = 5000;
    private TrafficLight _light1, _light2;
    private LightTimer _timer1,_timer2;

    /**
     * Constructor for objects of class DrawingPanel
     */
    public DrawingPanel()
    {
        // initialise instance variables
        super();
        this.setBackground(Color.CYAN);
        _light1 = new TrafficLight(50,50);
        _light2 = new TrafficLight(200,50);
        _timer1 = new LightTimer(INTERVAL1,this);
        _timer2 = new LightTimer(INTERVAL2,this);
        _timer1.start();
        _timer2.start();
    }

    public void cycle(){
        _light1.cycle();
        _light2.cycle();
        this.repaint();
        }

        public void paintComponent(Graphics pen)
        {
        super.paintComponent(pen);
        Graphics2D aBetterPen = (Graphics2D)pen;
        _light1.fill(aBetterPen);
        _light2.fill(aBetterPen);
    }

}
4

2 回答 2

3

以这种方式运行两个计时器是可以实现的。就个人而言,我会编写一个“信号”类,用它自己的时间和绘画例程控制单个灯光,但这不是你所要求的。

您需要做的是为每个信号维护某种状态变量并分别更新它们。

然后,您需要修改绘制代码以检测这些状态并采取适当的措施......例如

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestBlink {

    public static void main(String[] args) {
        new TestBlink();
    }

    public TestBlink() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private Timer blink1;
        private Timer blink2;

        private boolean light1 = false;
        private boolean light2 = false;

        public TestPane() {

            blink1 = new Timer(250, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    light1 = !light1;
                    repaint();
                }
            });
            blink2 = new Timer(1000, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    light2 = !light2;
                    repaint();
                }
            });

            blink1.start();
            blink2.start();

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            int radius = 20;
            int x = (getWidth() - (radius * 2)) / 2;
            int y = (getHeight() - (radius * 2)) / 2;

            Ellipse2D signal1 = new Ellipse2D.Float(x, y, radius, radius);
            Ellipse2D signal2 = new Ellipse2D.Float(x + radius, y, radius, radius);

            g2d.setColor(Color.RED);
            g2d.draw(signal1);
            if (light1) {
                g2d.fill(signal1);
            }
            g2d.setColor(Color.GREEN);
            g2d.draw(signal2);
            if (light2) {
                g2d.fill(signal2);
            }

            g2d.dispose();
        }
    }
}

更新

更好的解决方案(正如我之前所说的)是在单个类中包含单个序列的所有逻辑。这样可以隔离绘画并允许您更改每个序列的个人性质。

例如...

这是一个使用固定变化率的简单示例,因此每盏灯的时间都相同......

public class TraficLight01 extends JPanel {

    public static final int RADIUS = 20;

    private Timer timer;
    private int state = 0;

    public TraficLight01() {
        timer = new Timer(500, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                state++;
                if (state > 2) {
                    state = 0;
                }
                repaint();
            }
        });
        timer.start();
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(RADIUS, (RADIUS + 1) * 3);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();
        int radius = 20;
        Ellipse2D light = new Ellipse2D.Float(0, 0, RADIUS, RADIUS);
        int x = (getWidth() - radius) / 2;
        int y = ((getHeight()- (radius * 3)) / 2) + (radius * 2);

        Color color[] = new Color[]{Color.RED, Color.YELLOW, Color.GREEN};
        for (int index = 0; index < color.length; index++) {
            g2d.translate(x, y);
            g2d.setColor(color[index]);
            g2d.draw(light);
            if (state == index) {
                g2d.fill(light);
            }
            g2d.translate(-x, -y);
            y -= radius + 1;
        }
        g2d.dispose();
    }        
}

或者你为每盏灯提供一个可变的间隔......

public static class TraficLight02 extends JPanel {

    public static final int RADIUS = 20;

    private Timer timer;
    private int state = 0;

    // Green, Yellow, Red
    private int[] intervals = new int[]{3000, 500, 3000};

    public TraficLight02() {
        timer = new Timer(intervals[0], new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                timer.stop();
                state++;
                if (state > 2) {
                    state = 0;
                }
                timer.setInitialDelay(intervals[state]);
                repaint();
                timer.restart();
            }
        });
        timer.start();
        timer.setRepeats(false);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(RADIUS, (RADIUS + 1) * 3);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();
        int radius = 20;
        Ellipse2D light = new Ellipse2D.Float(0, 0, RADIUS, RADIUS);
        int x = (getWidth() - radius) / 2;
        int y = ((getHeight()- (radius * 3)) / 2) + (radius * 2);

        Color color[] = new Color[]{Color.GREEN, Color.YELLOW, Color.RED};
        for (int index = 0; index < color.length; index++) {
            g2d.translate(x, y);
            g2d.setColor(color[index]);
            g2d.draw(light);
            if (state == index) {
                g2d.fill(light);
            }
            g2d.translate(-x, -y);
            y -= radius + 1;
        }
        g2d.dispose();
    }        
}

改变这两个概念以通过一种setter方法以可变间隔播种它们并不需要太多。

同样,您可以使用三个Timers,每次触发一个,您只需启动下一个。通过这种方式,您可以定义一系列计时器,每个计时器在其父级完成后以不同的间隔触发......

于 2013-06-26T01:27:06.940 回答
0

作为说明,您的评论

它给了我一个有点随机的光变化,而不是一个很好的循环。

你期待它是什么样子的?

使用您设置的时间间隔,它可能看起来有些随机,但它实际上是有效的,即您的间隔会像这样工作(我对 Interval 变量的假设)

Time(s)    1    2   3   4   5   6   7   8   9   10   11   12   13   14   15   16
Light1         ON      OFF     ON      OFF      ON        OFF       ON        OFF
Light2                      ON                  OFF                      ON
于 2013-06-26T01:35:47.583 回答