栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

问题:创建一个非常准确的Swing计时器

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

问题:创建一个非常准确的Swing计时器

好的,所以我一直在看一些代码(我在上一个关于卡拉OK计时器的问题中发布的代码)

使用该代码,我建立了一些测量系统,

System.nanoTime()
通过
System.out.println()
它可以帮助我们了解正在发生的事情:

import java.awt.BorderLayout;import java.awt.Color;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.util.ArrayList;import javax.swing.AbstractAction;import javax.swing.JButton;import javax.swing.Jframe;import javax.swing.JOptionPane;import javax.swing.JTextPane;import javax.swing.SwingUtilities;import javax.swing.Timer;import javax.swing.text.Style;import javax.swing.text.StyleConstants;import javax.swing.text.Styleddocument;public class KaraokeTest {    private int[] timingsArray = {1000, 1000, 9000, 1000, 1000, 1000, 1000, 1000, 1000, 1000};//word/letters timings    private String[] individualWordsToHighlight = {" nHellon", " worldn", " Hello", " world", " Hello", " world", " Hello", " world", " Hello", " world"};//each individual word/letters to highlight    private int count = 0;    private final JTextPane jtp = new JTextPane();    private final JButton startButton = new JButton("Start");    private final Jframe frame = new Jframe();    //create Arrays of individual letters and their timings    final ArrayList<String> chars = new ArrayList<>();    final ArrayList<Long> charsTiming = new ArrayList<>();    public KaraokeTest() {        initComponents();    }    private void initComponents() {        frame.setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE);        frame.setResizable(false);        for (String s : individualWordsToHighlight) { String tmp = jtp.getText(); jtp.setText(tmp + s);        }        jtp.setEditable(false);        startButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) {     startButton.setEnabled(false);     count = 0;     charsTiming.clear();     chars.clear();     for (String s : individualWordsToHighlight) {         for (int i = 0; i < s.length(); i++) {  chars.add(String.valueOf(s.charAt(i)));  //System.out.println(String.valueOf(s.charAt(i)));         }     }     //calculate each letters timings     for (int x = 0; x < timingsArray.length; x++) {         for (int i = 0; i < individualWordsToHighlight[x].length(); i++) {  individualWordsToHighlight[x] = individualWordsToHighlight[x].replace("n", " ").replace("r", " ");//replace line breaks  charsTiming.add((long) (timingsArray[x] / individualWordsToHighlight[x].trim().length()));//dont count spaces  //System.out.println(timingsArray[x] / individualWordsToHighlight[x].length());         }     }     Timer t = new Timer(1, new AbstractAction() {         long startTime = 0;         long acum = 0;         long timeItTookTotal = 0;         long dif = 0, timeItTook = 0, timeToTake = 0;         int delay = 0;         @Override         public void actionPerformed(ActionEvent ae) {  if (count < charsTiming.size()) {      if (count == 0) {          startTime = System.nanoTime();          System.out.println("Started: " + startTime);      }      timeToTake = charsTiming.get(count);      acum += timeToTake;      //highlight the next word      highlightNextWord();      //System.out.println("Acum " + acum);      timeItTook = (acum - ((System.nanoTime() - startTime) / 1000000));      timeItTookTotal += timeItTook;      //System.out.println("Elapsed since start: " + (System.nanoTime() - startTime));      System.out.println("Time the char should take: " + timeToTake);      System.out.println("Time it took: " + timeItTook);      dif = (timeToTake - timeItTook);      System.out.println("Difference: " + dif);      //System.out.println("Difference2 " + (timeToTake - dif));      //calculate start of next letter to highlight less the difference it took between time it took and time it should actually take      delay = (int) (timeToTake - dif);      if (delay < 1) {          delay = 1;      }      //restart timer with new timings      ((Timer) ae.getSource()).setInitialDelay((int) timeToTake);//timer is usually faster thus the entire highlighting will be done too fast      //((Timer) ae.getSource()).setInitialDelay(delay);      ((Timer) ae.getSource()).restart();  } else {//we are at the end of the array      long timeStopped = System.nanoTime();      System.out.println("Stopped: " + timeStopped);      System.out.println("Time it should take in total: " + acum);      System.out.println("Time it took using accumulator of time taken for each letter: " + timeItTookTotal   + "nDifference: " + (acum - timeItTookTotal));      long timeItTookUsingNanoTime = ((timeStopped - startTime) / 1000000);      System.out.println("Time it took using difference (endTime-startTime): " + timeItTookUsingNanoTime   + "nDifference: " + (acum - timeItTookUsingNanoTime));      reset();      ((Timer) ae.getSource()).stop();//stop the timer  }  count++;//increment counter         }     });     t.setRepeats(false);     t.start(); }        });        frame.add(jtp, BorderLayout.CENTER);        frame.add(startButton, BorderLayout.SOUTH);        frame.pack();        frame.setVisible(true);    }    private void reset() {        startButton.setEnabled(true);        jtp.setText("");        for (String s : individualWordsToHighlight) { String tmp = jtp.getText(); jtp.setText(tmp + s);        }        JOptionPane.showMessageDialog(frame, "Done");    }    private void highlightNextWord() {        //we still have words to highlight        int sp = 0;        for (int i = 0; i < count + 1; i++) {//get count for number of letters in words (we add 1 because counter is only incrementd after this method is called) sp += 1;        }        while (chars.get(sp - 1).equals(" ")) { sp += 1; count++;        }        //highlight words        Style style = jtp.addStyle("RED", null);        StyleConstants.setForeground(style, Color.RED);        ((Styleddocument) jtp.getdocument()).setCharacterAttributes(0, sp, style, true);    }    public static void main(String[] args) {        SwingUtilities.invokeLater(new Runnable() { @Override public void run() {     new KaraokeTest(); }        });    }}

我的电脑上的输出是:

开始于:10289712615974

字符应花费的时间:166

花费时间:165

差异1

字符应花费的时间:166

花费时间:155

差异11

字符应花费的时间:166

花费时间:5

差异161

停止:10299835063084

总耗时:9960

使用每个字母所用时间的累加器所花费的时间:5542

差异:4418

使用差异所花费的时间(endTime-startTime):10122

差异:-162

因此,我的结论是Swing
Timer实际上运行的速度比我们预期的要快,因为

Timer
s中的代码
actionPerformed
不一定要花预期的字母突出显示时间的时间,这当然会引起雪崩效应,即,计时器运行的越快/越慢,则运行时间越大/差异将变小,下次执行的计时器
restart(..)
将在不同的时间进行,即更快或更慢。

在代码中执行以下操作:

//calculate start of next letter to highlight less the difference it took between time it took and time it should actually takedelay = (int) (timeToTake - dif);//restart timer with new timings//((Timer) ae.getSource()).setInitialDelay((int)timeToTake);//timer is usually faster thus the entire highlighting will be done too fast((Timer) ae.getSource()).setInitialDelay(delay);((Timer) ae.getSource()).restart();

产生更准确的结果(Ive的最大延迟是每个字母快4毫秒):

开始:10813491256556

字符应花费的时间:166

花费时间:164

差异2

字符应花费的时间:166

花费时间:164

差异2

字符应花费的时间:166

花费时间:162

差异4

停止:10823452105363

总耗时:9960

使用每个字母所用时间的累加器所花费的时间:9806

差异:154

使用差异所花费的时间(endTime-startTime):9960

差异:0



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/507674.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号