正確にするためSwingTimer
に、@Tony Docherty On CRが提案したロジックと例が好きです。ここにリンクがあります。
指定された単語を何度も強調表示するために、常に数マイクロ秒の遅延があります。ハイライトする単語が「こんにちは、お元気ですか」で、各単語の値が (遅延) である場合、それぞれ 200、300、400 ミリ秒の場合、タイマーにかかる実際の時間は常にそれ以上になります。200 ミリ秒ではなく、216 ミリ秒かかります。このように、言葉が多いと..結局余計な遅れが目立ちます。
各文字を強調表示する必要があります: 'h''e''l''l''0' はそれぞれ 200/length(つまり 5) = 40 ms になるはずです。各文字の後に遅延を設定します。
私の論理は、startTime
プロセスを開始する直前に、現在の時刻を言うことです。また、totalDelay
totalDelay+=delay/.length() を計算します。
ここで条件を確認してください: ( startTime+totalDelay-System.currentTime
) これが -ve の場合は、時間がかかることを意味するため、文字をスキップします。正の遅延が発生するまでチェックします。これは、今までのタイミングを追加していることを意味し、プロセスが開始されたときにプロセスにかかった時間の差でオーバーチェックします。
これにより、文字のハイライトがスキップされる場合があります。
しかし、何かが間違っています。なに、わかりにくい。たぶんループに問題があります。私はそれがループに入っているのを見ました(時間が -ve かどうかを確認するために)2回だけです。しかし、そうであってはなりません。また、次の遅延の設定についてもわかりません。何か案は?
SSCCE は次のとおりです。
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class Reminder {
private static final String TEXT = "arey chod chaad ke apnee saleem ki gali anarkali disco chalo";
private static final String[] WORDS = TEXT.split(" ");
private JFrame frame;
private Timer timer;
private StyledDocument doc;
private JTextPane textpane;
private int[] times = new int[100];
private long totalDelay=0,startTime=0;
private int stringIndex = 0;
private int index = 0;
public void startColoring() {
times[0]=100;times[9]=200;times[10]=200;times[11]=200;times[12]=200;
times[1]=400;times[2]=300;times[3]=900;times[4]=1000;times[5]=600;times[6]=200;times[7]=700;times[8]=700;
ActionListener actionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent)
{
doc.setCharacterAttributes(stringIndex, 1, textpane.getStyle("Red"), true);
stringIndex++;
try {
if (stringIndex >= doc.getLength() || doc.getText(stringIndex, 1).equals(" ")|| doc.getText(stringIndex, 1).equals("\n"))
{
index++;
}
if (index < WORDS.length) {
double delay = times[index];
totalDelay+=delay/WORDS[index].length();
/*Check if there is no -ve delay, and you are running according to the time*/
/*The problem is here I think. It's just entered this twice*/
while(totalDelay+startTime-System.currentTimeMillis()<0)
{
totalDelay+=delay/WORDS[index].length();
stringIndex++;
/*this may result into the end of current word, jump to next word.*/
if (stringIndex >= doc.getLength() || doc.getText(stringIndex, 1).equals(" ") || doc.getText(stringIndex, 1).equals("\n"))
{
index += 1;
totalDelay+=delay/WORDS[index].length();
}
}
timer.setDelay((int)(totalDelay+startTime-System.currentTimeMillis()));
}
else {
timer.stop();
System.err.println("Timer stopped");
}
} catch (BadLocationException e) {
e.printStackTrace();
}
}
};
startTime=System.currentTimeMillis();
timer = new Timer(times[index], actionListener);
timer.setInitialDelay(0);
timer.start();
}
public void initUI() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
doc = new DefaultStyledDocument();
textpane = new JTextPane(doc);
textpane.setText(TEXT);
javax.swing.text.Style style = textpane.addStyle("Red", null);
StyleConstants.setForeground(style, Color.RED);
panel.add(textpane);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
public static void main(String args[]) throws InterruptedException, InvocationTargetException {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
Reminder reminder = new Reminder();
reminder.initUI();
reminder.startColoring();
}
});
}
}
アップデート:
理解を深めるために:
@Tony Docherty によって与えられた EG :
「Test」という単語を 1 秒間強調表示する必要があるとします。したがって、各文字は 250 ミリ秒強調表示されます。元々の方法で物事を行うということは、文字ごとに250ミリ秒のタイマーを設定することを意味していましたが、各サイクルが実際に260ミリ秒かかり、「e」サイクルが400ミリ秒かかったとしましょう(おそらくGCまたはCPUサイクルを使用する何かが原因で)単語の終わりには、必要以上に 180 ミリ秒多くかかることになります。このエラーは、エラーが大きくなり、強調表示が視覚的に同期しなくなるまで、単語ごとに構築され続けます。
私が試みている方法は、この文字を x の時間強調表示する必要があると繰り返し言うのではなく、シーケンスの先頭からの各文字の時間を計算することです。つまり、T = 250、e = 500、s = 750、t = 1000。
したがって、実際の時間遅延を取得するには、開始時刻を加算して現在の時刻を減算する必要があります。上記のタイミングを使用して例を実行するには、次のようにします。
StartTime Letter Offset CurrentTime Delay ActualTimeTaken
100000 T 250 100010 240 250
100000 e 500 100260 240 400
100000 s 750 100660 90 100
100000 t 1000 100760 240 250
したがって、前の手紙からの時間の超過を考慮して、各手紙のタイミングが調整されていることがわかります。もちろん、タイミング オーバーランが大きすぎて、次の文字 (または 1 文字以上) を強調表示するのをスキップしなければならない可能性もありますが、少なくとも私は広く同期を維持します。
編集済み SSCCE
Update2
最初のフェーズでは、各単語のタイミングを取ります。つまり、ユーザーが ESC キーを押すと、特定の単語の時間が保存されます (曲がバックグラウンドで再生されるときに保存されます)。ESC キーを押すと、現在の単語が強調表示され、現在の単語に費やされた時間が表示されます。 word は配列に格納されます。私はタイミングを保存し続けます。ユーザーが終了したら、設定されたタイミングに従って単語を強調表示したいと思います。ここで、ユーザーによるタイミングが重要になります。タイミングが速ければ単語の強調表示も速くなり、遅ければその逆になります。
新しい更新: 進行状況
以下の回答は論理が異なりますが、驚いたことに、それらはほぼ同じように機能します。私がすべてのロジック(私のものを含む)で見つけた非常に奇妙な問題は、それらが数行で完全に機能するように見えることですが、その後速度が向上します。これも遅くはありませんが、大きな違いがあります。
また、私が別の方法で考える必要があると思われる場合は、あなたの提案を高く評価します.