[英]Timer speeds up when moving mouse over Chrome webpage elements
我創建了一個時間間隔以顯示一天中高速公路上的密度。 數據保存在double[][]
數組data
,其中data.length
為2880(每個索引代表30秒的間隔),而data[0].length
為約450(表示高速公路路段長度的三次插值) )。
我的延時代碼如下:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.Timer;
public class TimeLapse extends JPanel {
static double[][] data;
int index = 0;
double max;
double lineWidth;
Timer timer;
final JProgressBar progressBar = new JProgressBar(0, 2879);
BufferedImage[] images;
Color colors[][];
public static void main(String[] args) {
data=getData(); //arbitrary method to get interpolated data
new TimeLapse(data, 90);
}
public TimeLapse(double[][] data1, double max) {
data = data1;
this.max = max;
JFrame frame = new JFrame("Timelapse");
frame.setPreferredSize(new Dimension(800, 600));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.NORTH;
c.gridwidth = 1;
c.gridx = 0;
c.gridheight = 1;
c.weightx = 1;
c.weighty = .01;
c.gridy = 0;
frame.add(progressBar, c);
c.anchor = GridBagConstraints.SOUTH;
c.gridy = 1;
c.gridheight = 9;
c.weighty = 1;
frame.add(this, c);
frame.pack();
getColorArray();
frame.setVisible(true);
int dataLength;
dataLength = data.length;
// Make the animation 5 seconds long
int delay = (int) (5000d / dataLength);
timer = new Timer(delay, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updateIndex();
repaint();
Toolkit.getDefaultToolkit().sync();
}
});
timer.start();
}
private void getColorArray() {
double cutOff = max / 2;
colors = new Color[data.length][data[0].length];
for (int index = 0; index < data.length; index++) {
for (double x = 0; x < data[0].length; x++) {
colors[index][(int) x] =
getColor(data[index][(int) x], cutOff);
}
}
}
private void updateIndex() {
index = index < data.length - 1 ? index + 1 : 0;
progressBar.setValue(2879 * index / data.length);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
int panelHeight = getHeight();
lineWidth = ((double) getWidth()) / ((double) (data[0].length));
// guaranteed counter, as doing it in timer's ActionListener could overlap with rendering
for (double x = 0; x < data[0].length; x++) {
g2.setColor(colors[index][(int) x]);
double rectHeight = panelHeight * data[index][(int) x] / max;
g2.fillRect((int) (x * lineWidth),
(int) (panelHeight - rectHeight),
(int) (lineWidth + 1), (int) rectHeight + 1);
}
g2.dispose();
}
private Color getColor(double value, double cutOff) {
int hueR, hueG, hueB = 0;
if (value < cutOff) {
hueG = 255;
hueR = (int) (255 * value / (cutOff));
} else if (max != cutOff) {
hueR = 255;
hueG = (int) (255 - (255 * (value - cutOff) / (max - cutOff)));
} else {
hueR = 255;
hueG = 0;
}
hueR = (hueR < 0) ? 0 : ((hueR > 255) ? 255 : hueR);
hueG = (hueG < 0) ? 0 : ((hueG > 255) ? 255 : hueG);
hueB = (hueB < 0) ? 0 : ((hueB > 255) ? 255 : hueB);
return new Color(hueR, hueG, hueB);
}
}
動畫可以平穩運行,但是通常比我設置的時間要長五秒鍾,這要花很多時間才能確定面板中不斷着色和生成數百行線條。
為了驗證我是正確的,並且確實比預期的慢很多,我使用了Google Chrome小部件,當您用Google“秒表”計時時會顯示該小部件。 這樣做,我發現當我運行秒表時,動畫會大大加快,並且每當我將鼠標移到某些元素上時(超鏈接,頂部的選項卡,以及似乎對鼠標懸停具有視覺響應的其他任何東西) 。 僅當我移動鼠標或運行秒表時才會發生這種情況。 保持鼠標仍然不能加快速度,並且在將鼠標懸停在Chrome上時似乎只有這種行為(即,其他任何應用程序都可以)。 誰能解釋這種奇怪的行為?
編輯:重新加載選項卡時也會發生,但重新加載后不會發生。
編輯2:我現在肯定知道計時器正在加速。 我創建了一個帶有計時器的小類,該計時器每毫秒打印一次遞增的索引:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
public class TimerTest {
static int index = 0;
public static void main(String[] args) {
Timer t = new Timer(1, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(index++);
}
});
t.start();
while (true) {
}
}
}
這與時間流逝類具有完全相同的行為,將鼠標移到Chrome的元素上時可以大大加快速度。 我相信原因是,在這種情況下, println
是一種慢速方法,並且執行速度比計時器更新慢。 再次,有人可以解釋為什么Chrome特別加快備份計時器的速度嗎?
繪畫方法僅用於繪畫。
您不應在繪畫方法中更改類的屬性。
那就是您無法控制Swing確定何時需要重新粉刷組件。 因此,可能有一些系統調用導致組件重新粉刷,因此比您想象的更頻繁地更改屬性。
例如,您不應該更新“索引”變量或進度條值。 相反,您的Timer應該調用一個方法來更改這些屬性,然后該方法應該在面板上調用重新繪制。
這僅在我移動鼠標時發生
也許您在面板上有工具提示,這將導致它重新粉刷。
這很容易測試,只需在paintComponent()方法中添加System.out.println(...)語句,以查看它的顯示頻率是否比Timer的5秒還要頻繁。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.