Java 做一个FPS淋浴?

Java 做一个FPS淋浴?,java,frame-rate,Java,Frame Rate,我试图用FPS显示来制作一个字符串,但是,我实际上如何获得我的程序FPS呢?我想和你一起做 g.drawString(getFPS(), 10, 10) 如何获取FPS?此代码为我完成此操作。将其放入主程序循环中: //To Measure FPS private long now; private int framesCount = 0; private int framesCountAvg=0; private long framesTimer=0; //Main Game Loop

我试图用FPS显示来制作一个字符串,但是,我实际上如何获得我的程序FPS呢?我想和你一起做

g.drawString(getFPS(), 10, 10)

如何获取FPS?

此代码为我完成此操作。将其放入主程序循环中:

//To Measure FPS
private long now;
private int framesCount = 0;
private int framesCountAvg=0; 
private long framesTimer=0;

//Main Game Loop
    while (isRunning)
    {
        //Record the time before update and draw
        long beforeTime = System.nanoTime();
        //... Update program & draw program...
        // DRAW FPS: 
        now=System.currentTimeMillis(); 
        gEngine.drawFPS(c, framesCountAvg);
        framesCount++; 
        if(now-framesTimer>1000)
        { 
              framesTimer=now; 
              framesCountAvg=framesCount; 
              framesCount=0; 
        }}

调用“gEngine.drawFPS”只是告诉我的主绘制方法将fps包含在屏幕顶部(c是我的画布)-你可以使用类似的方法来给出“g”将正确的FramesContavg数据分类以绘制

计算经过的时间,
1000/elapsedTime
将成为您的fps。

虽然这个问题听起来有点模糊,但我仍会尽我所能回答它。因为最初的帖子可以追溯到2011年,所以OP很可能不会从我的回答中受益。不过,希望它能为那些跟随的人提供更好的立足点(前两个答案似乎有点凌乱和简洁)

下面是我经常用来收集和显示各种Java GUI应用程序的帧速率的代码片段:

public class FrameRateCounter {

    private Map<Long, Long> measurementTimes;


    public FrameRateCounter() {
        measurementTimes = new HashMap<Long, Long>();
    }

    public synchronized void submitReading() {
        long measurementTime = System.nanoTime();
        long invalidationTime = System.nanoTime() + 1000000000;
        measurementTimes.put(measurementTime, invalidationTime);
    }

    public int getFrameRate() {
        performInvalidations();
        return measurementTimes.size();
    }

    private synchronized void performInvalidations() {
        long currentTime = System.nanoTime();
        Iterator<Long> i = measurementTimes.keySet().iterator();
        while(i.hasNext()) {
            long measurementTime = i.next();
            long invalidationTime = measurementTimes.get(measurementTime);
            if(invalidationTime < currentTime) {
                i.remove();
            }
        }
    }
}
公共类FrameRateCounter{
私人地图测量时间;
公共帧率计数器(){
measurementTimes=新HashMap();
}
公共同步作废提交处理(){
long measurementTime=System.nanoTime();
长失效时间=System.nanoTime()+100000000;
measurementimes.put(measurementime,invalizationtime);
}
public int getFrameRate(){
performInvalidations();
返回measurementTimes.size();
}
私有同步的void performInvalidations(){
长currentTime=System.nanoTime();
迭代器i=measurementTimes.keySet().Iterator();
while(i.hasNext()){
长测量时间=i.next();
长失效时间=measurementTime.get(measurementTime);
if(失效时间<当前时间){
i、 删除();
}
}
}
}
我的方法(相对于以前的解决方案)的明显优势是:

  • 关注点分离-您不希望FPS计数计算之类的琐碎事情污染程序的“主循环”。因此,将此逻辑隔离到单独的组件/类中
  • GUI组件框架的独立性-最好尽可能避开依赖于框架的解决方案。在当前情况下,这很容易-只要避免在计算中引用
    图形
    JLabel
    之类的内容,就可以了
  • 存储在hashmap中的所有度量值——Hashmaps以其快速的查找时间而闻名(时间复杂度接近O(1))。因此,进行必要的比较不会对应用程序的总体性能产生任何明显的影响
  • 可以与多个
    javax.Swing.Timer
    s或线程一起使用-在从另一个计时器/线程运行
    getFrameRate()
    时,对试图评估其性能的计时器/线程调用
    submitrading()
    ,以获得结果(例如,您可以将其写入
    JLabel
    文件等)
  • (注:请注意,使用Swing时,所有绘制操作都需要在事件调度程序线程(EDT)上完成。因此,如果不使用特殊命令(如
    SwingUtilities.invokeLater(..)
    ),则不应将任何绘制工作委托给其他(原始)线程


    希望这有帮助

    请提供更多细节。我只想有一个字符串显示我的FPS。