簡體   English   中英

將鼠標移到Chrome網頁元素上時計時器加速

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM