提问者:小点点

如何在java中使用定时器类


我正在努力弄清楚计时器类是如何工作的,我可以使用它。我在网上寻找答案,尽管我能找到一个对像我这样的初学者来说足够简单的解释。如果有人发送一个很棒的计时器类的链接,我将不胜感激,或者甚至向我解释我应该在我的代码中做什么。谢谢!

    public class movement {
    private JComponent jt; // the JLabel (my game character)
    private InputMap ip;
    private ActionMap ap;
    private String comm; // the ActionMapKey
    private KeyStroke key;
    private int movement;
public movement(JComponent jt, InputMap ip,ActionMap ap, String comm,KeyStroke key,int movement){
    this.jt = jt;
    this.ip = ip;
    this.ap= ap;
    this.comm = comm;
    this.key = key;
    this.movement = movement;
}
public void newAction(){
    this.ip  = this.jt.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
    this.ip.put(key, comm);
    this.ap = this.jt.getActionMap();
    this.ap.put(this.comm, new AbstractAction() {


        @Override
        public void actionPerformed(ActionEvent arg0) {
            int originaly = jt.getY();
            if(key ==  KeyStroke.getKeyStroke(KeyEvent.VK_UP,0)){



                if(originaly==jt.getY()){
                    // how do i make this action animated? i want the JLabel to look like its moving up (like a jump) 
                    // after the up key is pressed 
                    // i dont really understand how to use the timer class to make it animated .. thanks!
                    jt.setBounds(jt.getX(),jt.getY()+movement , 50, 50);
                    //timer pause for 0.1 secs
                    jt.setBounds(jt.getX(),jt.getY()+movement , 50, 50);
                    //timer pause for 0.1 secs...
                    // can also be in a while loop until the y is 50 higher than original y. 
                }

            }
            else{
            jt.setBounds(jt.getX()+movement,jt.getY() , 50, 50);
            }
        }
    });

}
}

共2个答案

匿名用户

好吧,所以你的问题不在于计时器,而在于理解动画是如何实现的。

  • 动画是一种随时间变化的状态
  • ATimer是一个伪循环,它在迭代之间具有指定的延迟

好的,那么这有什么帮助呢?基本上,您需要制作一个对象从当前位置移动到新位置并再次返回的概念(上下跳跃)

这就是您的Timer的用武之地。Timer提供了一个状态和下一个状态之间的延迟,该延迟应该足够长以供用户感知

这是一个非常基本的示例,但它演示了基本原理。键绑定Action不负责更改位置,它负责更改状态,然后由Timer执行。为什么?想象一下,现在您有其他键绑定(左和右),它们不应该更改对象的状态,因为这些更改可能会冲突。相反,它们设置了一个状态标志,然后用于确定在状态更新时应该发生什么。

对象有一个yPos,并且可以通过一个更改值(yDelta)来执行,该更改值会影响实际应用于对象的更改。虽然跳转true,但对象被移动到其最顶层的高度并再次向下移动。一旦完成此循环,跳转状态将被重置,这意味着您不能一直按Space在空中执行多次跳转……因为这是不可能的;)

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.event.KeyEvent;
import java.io.IOException;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

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

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

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

    public class TestPane extends JPanel {

        private int yPos = 200;
        private int yDelta = -1;

        private boolean jump = false;

        public TestPane() {
            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap am = getActionMap();

            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "space");
            am.put("space", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    jump = true;
                }
            });
            Timer timer = new Timer(5, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (jump) {
                        if (yPos > 200) {
                            yPos = 200;
                            yDelta *= -1;
                            jump = false;
                        } else if (yPos < 150) {
                            yPos = 150;
                            yDelta *= -1;
                        } else {
                            yPos += yDelta;
                        }
                        repaint();
                    }
                }
            });
            timer.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 x = (getWidth() - 5) / 2;
            g2d.fillRect(x, yPos - 10, 10, 10);
            g2d.dispose();
        }

    }

}

太长别读了

现在,这是一个过于简化的例子,它没有讨论帧速率、地役权或重力等等。你可以看看这个例子,它展示了一个可变增量的概念,它随着时间的推移而下降,应用了一个(非常基本的)重力概念。

还有其他方法可以实现类似的结果,这取决于你想做什么,但它们围绕着相同的概念。

如果你真的很勇敢,你可以看看我如何用一个线程来实现缓动函数,这个线程破坏了(相当IMHO)缓动的概念——或者变速动画。你也可以看看Java图像沿着列表中的点移动,并使用线性插值来谈论更多关于可变动画路径的内容——其中t(时间)是可变的,它允许你根据动画播放的时间和你希望它播放的时间来为你计算一个值。

如果你想知道我为什么要提到它——那是因为你可以做这样的事情,这大大扩展了你的能力。

但是,所有这些东西的核心是Timer

匿名用户

好的,所以当你说“定时器暂停0.1秒”时,我想你可以使用Thread.睡眠(100);100-