如何在 Java Swing 中实现多个计时器

时间:2021-05-18 23:22:52

标签: java swing

我的图标集有一个 timer 可以为这些图标设置动画。基本上 - 我有一张世界地图作为背景和汽车,飞机等。图标“浮动”在这张地图上。我正在使用 swing timer 来执行此操作,但它会在 JPanel 呈现后立即显示所有图标并开始它们的运动。我希望他们随机出现/开始他们的动作,我想实现第二个 timer 并且每 10 秒创建一个随机数 - 1 或 2 - (例如,如果数字等于 1,则开始此特定图标的动画)。

Timer timer;
....
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(world_map,0,0, getWidth(), getHeight(), null);
        for (Transportation item : transportations) {
            item.drawTransportation(g);
            g2d.drawLine(item.start_x+25,item.start_y+25,item.finish_x+25,item.finish_y+25);
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        for (Transportation item : transportations) {
            if (item.x > item.finish_x) {
                item.x -= 1;
            }
            else if (item.x < item.finish_x) {
                item.x += 1;
            }

            if (item.y > item.finish_y) {
                item.y -= 1;
            }
            else if (item.y < item.finish_y) {
                item.y += 1;
            }
        }
        repaint();
    }

    public void startCoords() {
        for (Transportation item : transportations) {
            item.setMap_coords(map_coords);
            item.setCountries(countries);
        }

        timer = new Timer(10,this);
        timer.start();
    }

1 个答案:

答案 0 :(得分:2)

“一般来说”,多个 Swing Timer 不能很好地扩展。如果您正在尝试开发某种类型的游戏,将所有“更新”保持在一个“游戏循环”中会在控制事情方面增加很多好处。

所以,这是一个非常简单的概念。当 Timer 滴答作响时,它会检查已经过去的时间量,当达到某种增量时,它会生成一堆“随机内容”。

我还放了一个小计数器,这样你就可以看到沿途确实有一些事情正在发生。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class Test {

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

    public Test() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private List<Point> points = new ArrayList<>(25);
        private Timer timer;

        private Instant clock;
        private Random rnd = new Random();

        public TestPane() {
            setBackground(Color.BLACK);
            setForeground(Color.WHITE);
            timer = new Timer(5, new ActionListener() {

                private Instant anchorTime;

                @Override
                public void actionPerformed(ActionEvent arg0) {
                    if (anchorTime == null) {
                        anchorTime = Instant.now();
                    }

                    // You could just do a mod 10, but I'm feeling lazy
                    if (Duration.between(anchorTime, Instant.now()).getSeconds() >= 10) {
                        anchorTime = Instant.now();
                        generateRandomThing();
                    }

                    repaint();
                }
            });
            timer.setInitialDelay(0);
            clock = Instant.now();
        }

        protected void generateRandomThing() {
            for (int index = 0; index < 10; index++) {
                int x = 10 + (int) (rnd.nextDouble() * (getWidth() - 20));
                int y = 10 + (int) (rnd.nextDouble() * (getHeight() - 20));
                Point p = new Point(x, y);
                points.add(p);
            }
        }

        @Override
        public void addNotify() {
            super.addNotify();
            clock = Instant.now();
            timer.start();
        }

        @Override
        public void removeNotify() {
            super.removeNotify(); //To change body of generated methods, choose Tools | Templates.
            timer.stop();
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            Duration runTime = Duration.between(clock, Instant.now());
            g2d.setColor(Color.WHITE);
            FontMetrics fm = g2d.getFontMetrics();

            String text = Long.toString(runTime.getSeconds());
            int x = 10;
            int y = 10 + fm.getAscent();
            g2d.drawString(text, x, y);

            g2d.setColor(Color.RED);
            for (Point p : points) {
                g2d.fillOval(p.x - 5, p.y - 5, 10, 10);
            }

            g2d.dispose();
        }

    }
}

这绝不是您可以采取的唯一方法,这只是可扩展性和控制问题之一。

相关问题