2015-12-06 3 views
1

У меня есть список JPanels, который я хочу отобразить как «слайд-шоу», когда один JPanel исчезает, и следующая JPanel в списке исчезает. Это код I я возился с:Java Fade In и Out два JPanels в то же время

public float opacity = 0f; 
    private Timer fadeTimer; 
    private boolean out; 

    public void fadeIn() 
    { 
    out = false; 
    beginFade(); 
    } 

    public void fadeOut() 
    { 
    out = true; 
    beginFade(); 
    } 

    private void beginFade() 
    { 
    fadeTimer = 
     new javax.swing.Timer(75,this); 
    fadeTimer.setInitialDelay(0); 
    fadeTimer.start(); 
    } 

    public void actionPerformed(ActionEvent e) 
    { 
    if (out) 
    { 
     opacity -= .03; 
     if(opacity < 0) 
     { 
     opacity = 0; 
     fadeTimer.stop(); 
     fadeTimer = null; 
     } 
    } 
    else 
    { 
     opacity += .03; 
     if(opacity > 1) 
     { 
     opacity = 1; 
     fadeTimer.stop(); 
     fadeTimer = null; 
     } 
    } 


    repaint(); 
    } 
    public void paintComponent(Graphics g) 
    { 
    ((Graphics2D) g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity)); 
    g.setColor(getBackground()); 
    g.fillRect(0,0,getWidth(),getHeight()); 
    } 

проблема в том, что она исчезает несколько раз, а иногда это не так, и в других случаях перехода очень лага. Я бы предпочел, что есть доля секунды, когда экран становится белым, между тем, когда один JPanel исчезает, а следующий JPanel исчезает. Кто-нибудь знает, как я могу это решить? Заранее спасибо.

+0

Возможный дубликат [этот вопрос] (HTTP://stackoverflow.com/questions/22275435/cardlayout-showing-two-panels-flashing). Пожалуйста, см. Мой ответ, поскольку я думаю, что это может вам помочь. –

ответ

1

Таким образом, при решении этих проблем обычно лучше уменьшить количество Timer, которое у вас есть, так как каждый таймер будет отправлять несколько событий в очередь диспетчеризации событий (там есть собственные обновления галочек, а также перекрашивать события). Вся эта деятельность может снизить производительность системы.

Анимация также является иллюзией изменений во времени, с этой целью, а не для того, чтобы попытаться зациклиться от начальной точки до конечной точки, вы должны решить, как долго вы хотите, чтобы анимация запускалась и вычисляли ход времени и обновить значения соответственно (это больше из цикла анимации на основе временной шкалы). Это может помочь уменьшить появление «отстающих»

Обычно я использовать Timing Framework для достижения этой цели, но вы также можете взглянуть на Trident рамки или Universal Tween Engine которые также обеспечивают комплексную поддержку анимации для Swing.

Этот пример очень плотно связан с его целью. Лично я обычно имел абстрактную концепцию «аниматируемого» объекта, который, вероятно, имел бы только метод update(float), который затем был бы расширен, чтобы поддерживать другие объекты, но я оставлю это вам в орех.

Еще одна проблема - убедиться, что компонент полностью прозрачен для начала (setOpaque(false)), что позволяет нам подделывать полупрозрачность компонента во время анимации.

Как правило, я всегда рекомендую вам переопределить paintComponent, но есть несколько раз, когда это не подходит, это один из них. В принципе, чтобы облегчить переход от одного компонента к другому, нам нужно контролировать альфа-уровень ВСЕХ дочерних компонентов внутри компонента, это когда переопределение paint будет лучшим выбором.

Fade

нб: Код устанавливается для запуска на отметке 25fps, но программа для захвата снимков экрана на примерно 8fps

import java.awt.AlphaComposite; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import java.text.NumberFormat; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.imageio.ImageIO; 
import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class FadeTest { 

    public static void main(String[] args) { 
     new FadeTest(); 
    } 

    public FadeTest() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        try { 
         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
         ex.printStackTrace(); 
        } 

        BufferedImage img1 = ImageIO.read(new File("C:\\Users\\shane\\Dropbox\\Ponies\\sillydash-small.png")); 
        BufferedImage img2 = ImageIO.read(new File("C:\\Users\\shane\\Dropbox\\Ponies\\SmallPony.png")); 

        AlphaPane pane1 = new AlphaPane(); 
        pane1.add(new JLabel(new ImageIcon(img1))); 
        pane1.setAlpha(1f); 

        AlphaPane pane2 = new AlphaPane(); 
        pane2.add(new JLabel(new ImageIcon(img2))); 
        pane2.setAlpha(0f); 

        JFrame frame = new JFrame("Testing"); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        frame.setLayout(new GridBagLayout()); 
        GridBagConstraints gbc = new GridBagConstraints(); 
        gbc.gridx = 1; 
        gbc.gridy = 1; 
        gbc.weightx = 1; 
        gbc.weighty = 1; 
        gbc.fill = GridBagConstraints.BOTH; 
        frame.add(pane1, gbc); 
        frame.add(pane2, gbc); 
        frame.pack(); 
        frame.setLocationRelativeTo(null); 
        frame.setVisible(true); 

        MouseAdapter ma = new MouseAdapter() { 

         private AnimationController controller; 

         @Override 
         public void mouseClicked(MouseEvent e) { 
          try { 
           if (controller != null) { 
            controller.stop(); 
           } 
           controller = new AnimationController(4000); 

           boolean fadeIn = pane1.getAlpha() < pane2.getAlpha(); 

           controller.add(controller.new AlphaRange(pane1, fadeIn)); 
           controller.add(controller.new AlphaRange(pane2, !fadeIn)); 

           controller.start(); 
          } catch (InvalidStateException ex) { 
           ex.printStackTrace(); 
          } 
         } 

        }; 
        pane1.addMouseListener(ma); 
        pane2.addMouseListener(ma); 

       } catch (IOException ex) { 
        ex.printStackTrace(); 
       } 
      } 
     }); 
    } 

    public class AnimationController { 

     private List<AlphaRange> animationRanges; 
     private Timer timer; 
     private Long startTime; 
     private long runTime; 

     public AnimationController(int runTime) { 
      this.runTime = runTime; 
      animationRanges = new ArrayList<>(25); 
     } 

     public void add(AlphaRange range) { 
      animationRanges.add(range); 
     } 

     public void start() throws InvalidStateException { 
      if (timer == null || !timer.isRunning()) { 

       timer = new Timer(40, new ActionListener() { 
        @Override 
        public void actionPerformed(ActionEvent e) { 
         if (startTime == null) { 
          startTime = System.currentTimeMillis(); 
         } 
         long duration = System.currentTimeMillis() - startTime; 
         float progress = (float) duration/(float) runTime; 
         if (progress > 1f) { 
          progress = 1f; 
          stop(); 
         } 

         System.out.println(NumberFormat.getPercentInstance().format(progress)); 

         for (AlphaRange range : animationRanges) { 
          range.update(progress); 
         } 
        } 
       }); 
       timer.start(); 

      } else { 
       throw new InvalidStateException("Animation is running"); 
      } 
     } 

     public void stop() { 
      if (timer != null) { 
       timer.stop(); 
      } 
     } 

     public class AlphaRange { 

      private float from; 
      private float to; 

      private AlphaPane alphaPane; 

      public AlphaRange(AlphaPane alphaPane, boolean fadeIn) { 
       this.from = alphaPane.getAlpha(); 
       this.to = fadeIn ? 1f : 0f; 
       this.alphaPane = alphaPane; 
      } 

      public float getFrom() { 
       return from; 
      } 

      public float getTo() { 
       return to; 
      } 

      public float getValueBasedOnProgress(float progress) { 

       float value = 0; 
       float distance = to - from; 
       value = (distance * progress); 
       value += from; 

       return value; 

      } 

      public void update(float progress) { 
       float alpha = getValueBasedOnProgress(progress); 
       alphaPane.setAlpha(alpha); 
      } 

     } 

    } 

    public class InvalidStateException extends Exception { 

     public InvalidStateException(String message) { 
      super(message); 
     } 

     public InvalidStateException(String message, Throwable cause) { 
      super(message, cause); 
     } 

    } 

    public class AlphaPane extends JPanel { 

     private float alpha; 

     public AlphaPane() { 
      setOpaque(false); 
     } 

     @Override 
     public void paint(Graphics g) { 
      Graphics2D g2d = (Graphics2D) g.create(); 
      g2d.setComposite(AlphaComposite.SrcOver.derive(alpha)); 
      super.paint(g2d); 
      g2d.dispose(); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      // Fake the background 
      g.setColor(getBackground()); 
      g.fillRect(0, 0, getWidth(), getHeight()); 
     } 

     public void setAlpha(float value) { 
      if (alpha != value) { 
       this.alpha = Math.min(1f, Math.max(0, value)); 
       repaint(); 
      } 
     } 

     public float getAlpha() { 
      return alpha; 
     } 

    } 

} 
+0

(1+) ваше решение работает :) Mine does not; (Любая идея, почему мой не работает? – camickr

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

  • Нет связанных вопросов^_^