2013-09-21 3 views
3

Invoke javax.swing.Timer # старт() одновременно,javax.swing.Timer замедление Java7u40

7u25 не проблема.

enter image description hereenter image description here

но 7u40 большая проблема.

enter image description hereenter image description here

Слишком лага Invoke ActionListener # actionPerformed. (в основном в то же время вызывают u25)

Полностью другой ход между u25 и u40. (Я использую Windows 8) Я сообщаю об ошибке, но не добавляю систему отслеживания ошибок. Oracle сокрушительные качания приложений?

import java.awt.*; 
import java.awt.event.*; 

import javax.swing.*; 

public class TimerProblem extends JComponent { 

     int red = 0; 

     TimerProblem(final long startMs) { 
       setPreferredSize(new Dimension(10, 10)); 

       Timer t = new Timer(16, new ActionListener() { 

         @Override 
         public void actionPerformed(ActionEvent e) { 
           red = (int)(System.currentTimeMillis() - startMs) % 255; 
           repaint(); 
         } 

       }); 
       t.setInitialDelay(1000); 
       t.start(); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
       g.setColor(new Color(red, 255 - red, 0)); 
       g.fillRect(0, 0, getWidth(), getHeight()); 
     } 

     public static void main(String[] args) { 
       JFrame f = new JFrame(); 
       Container c = f.getContentPane(); 

       c.setLayout(new GridLayout(10, 10)); 
       long startMs = System.currentTimeMillis(); 
       for (int i = 0; i < 100; i++) { 
         c.add(new TimerProblem(startMs)); 
       } 
       f.pack(); 
       f.setVisible(true); 
     } 

} 
+1

+1 Oracle дробильно свинг приложений? Похоже, так как есть две важные вещи безопасности независимо и preerelease для java8, тогда никто не знает, что происходит или нет, что-то ошибка или функция, кстати, вы можете [проверить, вызваны ли они на вашем ПК (я не выдаю)] (http://stackoverflow.com/questions/18918367/Java-Jpop upmenu-bug) – mKorbel

+0

лучше проверить со стандартным обновлением 25/33/40/50 – mKorbel

+0

Просто проверил ваш код. Тот же вопрос. У меня даже есть проблемы с запуском одного из моих приложений JavaFX. –

ответ

0

Наконец я пишу DIY класс управления перекрасить .. :(

import java.awt.event.*; 
import java.util.*; 

import javax.swing.*; 
import javax.swing.Timer; 

/** 
* EffectTimer 
*/ 
public class EffectTimer { 

    /** 
    * All of effect timers in instance of this class. 
    */ 
    static class GlobalTimer implements ActionListener { 

     List<EffectTimer> registeredEffects = new ArrayList<>(); 

     Timer timer = new Timer(16, this); 

     public void start(final EffectTimer t) { 
      SwingUtilities.invokeLater(new Runnable() { 

       @Override 
       public void run() { 
        internalStart(t); 
       } 

      }); 
     } 

     void internalStart(EffectTimer t) { 
      int initialDelay = Math.max(0, (int) (t.getEffectStartTime() - System.currentTimeMillis())); 
      if(timer.getInitialDelay() >= initialDelay) { 
       timer.setInitialDelay(initialDelay); 
      } 
      if(!registeredEffects.contains(t)) { 
       registeredEffects.add(t); 
       if(registeredEffects.size() == 1) { 
        timer.start(); 
       } 
      } 
     } 

     void stop(final EffectTimer t) { 
      SwingUtilities.invokeLater(new Runnable() { 

       @Override 
       public void run() { 
        registeredEffects.remove(t); 
        checkStop(); 
       } 

      }); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      long now = e.getWhen(); 

      Iterator<EffectTimer> iter = registeredEffects.iterator(); 
      while(iter.hasNext()) { 
       EffectTimer t = iter.next(); 
       long elapsedMs = now - t.getEffectStartTime(); 

       if(elapsedMs > 0) { 
        float p = elapsedMs/(float)t.getEffectLengthMs(); 
        if(p >= 1.0f) { 
         iter.remove(); 
         t.stop(); 
        } else { 
         if(t.isReversed()) { 
          p = 1.0f - p; 
         } 
         t.progressChanged(p); 
        } 
       } 
      } 

      checkStop(); 
     } 

     void checkStop() { 
      if(registeredEffects.isEmpty()) { 
       timer.stop(); 
      } 
     } 

     public int getRunningTimerCount() { 
      return registeredEffects.size(); 
     } 

     public void stopAll() { 
      SwingUtilities.invokeLater(new Runnable() { 

       @Override 
       public void run() { 
        registeredEffects.clear(); 
        checkStop(); 
       } 

      }); 
     } 

    } 

    static final GlobalTimer GTIMER = new GlobalTimer(); 

    int effectLengthMs = -1; 

    long effectStartMs = -1; 

    float progress = 0.0f; 

    boolean reversed = true; 

    public long getEffectStartTime() { 
     return effectStartMs; 
    } 

    public int getEffectLengthMs() { 
     return effectLengthMs; 
    } 

    public void start(int lengthMs) { 
     start(lengthMs, System.currentTimeMillis()); 
    } 

    public void start(int lengthMs, long startMs) { 
     effectLengthMs = lengthMs; 
     effectStartMs = startMs; 

     reversed = false; 
     progress = 0.0f; 
     GTIMER.start(this); 
    } 

    public boolean isReversed() { 
     return reversed; 
    } 

    public void reverse(final int lengthMs) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       internalReverse(lengthMs); 
      } 

     }); 
    } 

    void internalReverse(int lengthMs) { 
     reversed = !reversed; 

     effectLengthMs = lengthMs; 
     int adjust = reversed ? (int)(lengthMs * (1.0f - progress)) : (int)(lengthMs * progress); 
     effectStartMs = System.currentTimeMillis() - adjust; 

     GTIMER.start(this); 
    } 

    final public void progressChanged(float p) { 
     progress = p; 
     run(p); 
    } 

    /** 
    * 0.0f to 1.0f effect progress. 
    * <code>Float.compare(progress, 1.0f) >= 0</code> to end progress. 
    */ 
    protected void run(float p) {} 

    public void stop() { 
     progress = reversed ? 0.0f : 1.0f; 
     GTIMER.stop(this); 
    } 

    public boolean isRunning() { 
     return 0.0f < progress && progress < 1.0f; 
    } 

    public float getProgress() { 
     return progress; 
    } 

    public static int getRunningTimerCount() { 
     return GTIMER.getRunningTimerCount(); 
    } 

    public static void stopAll() { 
     GTIMER.stopAll(); 
    } 

} 
1

Некоторые проблемы возникают в вашем примере:

  • распашные объекты GUI должны быть построены и управляться только на event dispatch thread.

  • Все экземпляры Swing Timer имеют общую нить, которая является насыщенной.

В зависимости от цели, некоторые альтернативные варианты:

  • Использование одного Timer экземпляра и выберите некоторую долю для обновления при пропорционально более высокой скорости. Пример ниже случайным образом выбирает N компонентов и обновляет их каждые 100 мс.

  • Использовать TexturePaint, как показано на рисунке here.

image

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.ArrayList; 
import java.util.Collections; 
import java.util.List; 
import java.util.Random; 
import javax.swing.*; 

/** @see https://stackoverflow.com/a/18936444/230513 */ 
public class BlinkenLights { 

    private static final int S = 24; 
    private static final int N = 10; 
    private static final Random r = new Random(); 
    private static final List<MyComponent> list = new ArrayList<MyComponent>(); 

    private static final class MyComponent extends JComponent { 

     public MyComponent() { 
      this.setOpaque(true); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(S, S); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      g.setColor(Color.getHSBColor(r.nextFloat()/6, 1, 1)); 
      g.fillRect(0, 0, getWidth(), getHeight()); 
     } 
    } 

    private static JPanel createPanel() { 
     final JPanel p = new JPanel(); 
     p.setLayout(new GridLayout(N, N)); 
     for (int i = 0; i < N * N; i++) { 
      MyComponent c = new MyComponent(); 
      p.add(c); 
      list.add(c); 
     } 
     Timer t = new Timer(1000/N, new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       Collections.shuffle(list, r); 
       for (int i = 0; i < N; i++) { 
        list.get(i).repaint(); 
       } 
      } 
     }); 
     t.start(); 
     return p; 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       JFrame f = new JFrame(); 
       f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       f.add(createPanel()); 
       f.pack(); 
       f.setLocationRelativeTo(null); 
       f.setVisible(true); 
      } 
     }); 
    } 
} 
+0

+1 для обходного пути, но между этими двумя JDK есть различие между ними, изображение добавлено в OP (вопрос не для добавления изображений) - это всего лишь мой сценарий тестирования (Win7 вместо OPs Win8) – mKorbel

+0

@mKorbel: Хорошая точка; пользователь должен [профиль] (http://stackoverflow.com/q/2064427/230513), чтобы узнать, насыщается ли EDT. – trashgod

+0

У нас есть внутренняя команда :-) для обновления до JRE 1.6/7 _... 40 с вручную un_install предыдущей версией или не обновлением и ожиданием «стабильной версии», а не моей заботой в этой компании .... – mKorbel

Смежные вопросы