2011-08-26 85 views
2

我有一个很长的重绘操作,我想限制速度,即确保它最多每N毫秒调用一次。摆动速率限制

我目前的解决方案有些不尽人意:我使用的时间较短的Swing Timer,当我得到一个事件时,我使用了restart()。这确保了如果事件在N毫秒的时间内发生,重绘将不会被触发(即重绘将发生在事件和N毫秒“安静”时段结束后)。

我想要确保重绘在第一个事件后至多N毫秒被调用,并且重绘期至多是N.任何想法? (没有记录在已启动的Timer上调用start的效果)。

回答

5

那里,因为我只知道来自本机OS的延迟,如果您将溢出此刷新率,然后出现RepaintManager错误,顺便说一句,你的主题是非常学术 延迟是最大刷新率的一个像素/每秒

this oneenter image description here

或另一个应该是不错的基础测试,直到/高达第一个错误(S)从缺憾的RepaintManager(然后可能锁定当前JVM实例)从代码 enter image description here

import java.awt.*; 
import java.awt.event.*; 
import java.util.*; 
import javax.swing.*; 
import javax.swing.SwingUtilities; 
import javax.swing.Timer; 

public class AnimationBackground { 

    public AnimationBackground() { 
     Random random = new Random(); 
     JFrame frame = new JFrame("Animation Background"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setResizable(false); 
     frame.setLayout(new GridLayout(0, 1, 10, 10)); 
     //frame.setLayout(new GridLayout(0, 3, 10, 10)); 
     //for (int iPanels = 0; iPanels < 3; iPanels++) { 
     for (int iPanels = 0; iPanels < 1; iPanels++) { 
      final MyJPanel panel = new MyJPanel(); 
      panel.setBackground(Color.BLACK); 
      for (int i = 0; i < 100; i++) { 
       Star star = new Star(new Point(random.nextInt(490), random.nextInt(490))); 
       star.setColor(new Color(100 + random.nextInt(155), 100 + random.nextInt(155), 100 + random.nextInt(155))); 
       star.setxIncr(-3 + random.nextInt(7)); 
       star.setyIncr(-3 + random.nextInt(7)); 
       panel.add(star); 
      } 
      panel.setLayout(new GridLayout(10, 1)); 
      JLabel label = new JLabel("This is a Starry background.", JLabel.CENTER); 
      label.setForeground(Color.WHITE); 
      panel.add(label); 
      JPanel stopPanel = new JPanel(); 
      stopPanel.setOpaque(false); 
      stopPanel.add(new JButton(new AbstractAction("Stop this madness!!") { 

       private static final long serialVersionUID = 1L; 

       @Override 
       public void actionPerformed(ActionEvent e) { 
        panel.stopAnimation(); 
       } 
      })); 
      panel.add(stopPanel); 
      JPanel startPanel = new JPanel(); 
      startPanel.setOpaque(false); 
      startPanel.add(new JButton(new AbstractAction("Start moving...") { 

       private static final long serialVersionUID = 1L; 

       @Override 
       public void actionPerformed(ActionEvent e) { 
        panel.startAnimation(); 
       } 
      })); 
      panel.add(startPanel); 
      frame.add(panel); 
     } 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       AnimationBackground animationBackground = new AnimationBackground(); 
      } 
     }); 
    } 

    class Star extends Polygon { 

     private static final long serialVersionUID = 1L; 
     private Point location = null; 
     private Color color = Color.YELLOW; 
     private int xIncr, yIncr; 
     static final int WIDTH = 500, HEIGHT = 500; 

     Star(Point location) { 
      int x = location.x; 
      int y = location.y; 
      this.location = location; 
      this.addPoint(x, y + 8); 
      this.addPoint(x + 8, y + 8); 
      this.addPoint(x + 11, y); 
      this.addPoint(x + 14, y + 8); 
      this.addPoint(x + 22, y + 8); 
      this.addPoint(x + 17, y + 12); 
      this.addPoint(x + 21, y + 20); 
      this.addPoint(x + 11, y + 14); 
      this.addPoint(x + 3, y + 20); 
      this.addPoint(x + 6, y + 12); 
     } 

     public void setColor(Color color) { 
      this.color = color; 
     } 

     public void move() { 
      if (location.x < 0 || location.x > WIDTH) { 
       xIncr = -xIncr; 
      } 
      if (location.y < 0 || location.y > WIDTH) { 
       yIncr = -yIncr; 
      } 
      translate(xIncr, yIncr); 
      location.setLocation(location.x + xIncr, location.y + yIncr); 
     } 

     public void setxIncr(int xIncr) { 
      this.xIncr = xIncr; 
     } 

     public void setyIncr(int yIncr) { 
      this.yIncr = yIncr; 
     } 

     public Color getColor() { 
      return color; 
     } 
    } 

    class MyJPanel extends JPanel { 

     private static final long serialVersionUID = 1L; 
     private ArrayList<Star> stars = new ArrayList<Star>(); 
     private Timer timer = new Timer(20, new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       for (Star star : stars) { 
        star.move(); 
       } 
       repaint(); 
      } 
     }); 

     public void stopAnimation() { 
      if (timer.isRunning()) { 
       timer.stop(); 
      } 
     } 

     public void startAnimation() { 
      if (!timer.isRunning()) { 
       timer.start(); 
      } 
     } 

     @Override 
     public void addNotify() { 
      super.addNotify(); 
      timer.start(); 
     } 

     @Override 
     public void removeNotify() { 
      super.removeNotify(); 
      timer.stop(); 
     } 

     MyJPanel() { 
      this.setPreferredSize(new Dimension(520, 520)); 
     } 

     public void add(Star star) { 
      stars.add(star); 
     } 

     @Override 
     public void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
      for (Star star : stars) { 
       g.setColor(star.getColor()); 
       g.fillPolygon(star); 
      } 
     } 
    } 
} 
+0

@trashgod我用于第一。附加图片,:-)不是这一个,但另一个:-) – mKorbel

+0

我不知道; 'javax.swing.Timer'应该足够了。当然,如果调整'AnimationTest'的大小,那么'repaint()'的速度会比标称的'Timer'的速度快得多。 – trashgod