2017-07-09 2 views
2

現在のところ、私のコードは、リストから最初のサイズから最終サイズにイメージをアニメーション化し、次のイメージですべてのイメージのアニメーションが完了し、すべてが最終サイズになるまで続きます。グループ別に画像リストをアニメーション化するJava Swing

package ui; 

import java.awt.Dimension; 
import java.awt.GridLayout; 
import java.awt.Image; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.ImageIcon; 
import javax.swing.JButton; 
import javax.swing.JPanel; 
import javax.swing.Timer; 

import utils.SudokuGen; 

// TODO: Auto-generated Javadoc 
/** 
* The Class ButtonPanel. 
*/ 
public class ButtonPanel extends JPanel implements ActionListener{ 

    /** The Constant serialVersionUID. */ 
    private static final long serialVersionUID = 1L; 

    /** The buttons. */ 
    private JButton[] buttons; 

    private int[] imgsize; 
    private int index,count; 
    private Timer timer; 
    private ImageButton images; 
    private static final int COUNT = 10; 
    private static final int INITSIZE = 32; 
    private static final int COLUMNS = 1; 
    private static final int ROWS = 9; 

    /** 
    * Instantiates a new button panel. 
    * 
    * @param puzzle The Sudoku matrix object 
    * @param images The images object 
    * @param sPanel The Sudoku JPanel 
    */ 
    public ButtonPanel(SudokuGen puzzle, ImageButton images, SudokuPanel sPanel){ 

     //Create an array of JButton with 9 elements 
     this.buttons = new JButton[puzzle.getMyboard().getNewnumbers().size()]; 

     this.images = images; 
     this.imgsize = new int[COUNT]; 
     for (int i=0;i<COUNT;i++){ 
      imgsize[i] = INITSIZE; 
     } 
     //Sets the layout to a 9*1 GridLayout with padding 5 
     this.setLayout(new GridLayout(ROWS,COLUMNS,5,5)); 

     //Load an image, create the MouseListener and add it at index i 
     for (int i=1;i<this.images.getImagelist().size();i++){ 
      ImageIcon image = new ImageIcon(this.images.getImagelist() 
        .get(i).getImage().getScaledInstance(32, 32, Image.SCALE_SMOOTH)); 
      buttons[i] = createMouseListener(image, i, puzzle, sPanel); 
      buttons[i].setPreferredSize(new Dimension(100, 100)); 
      this.add(buttons[i]); 
     } 

     index = 1; //first button 
     count = 0; //times to resize the button 

     timer = new Timer(5,this); 
     timer.start(); 
    } 

    public void set(int X){ 
     this.imgsize[index] = X; 
    } 

    /** 
    * Creates the mouse listener. 
    * 
    * @param image The image at index i 
    * @param i The index for the button i 
    * @param puzzle The Sudoku matrix object 
    * @param sPanel The Sudoku JPanel 
    * @return the JButton to add at index i 
    */ 
    private JButton createMouseListener(ImageIcon image, int i, SudokuGen puzzle, SudokuPanel sPanel){ 
     JButton button = new JButton(); 
     button.setIcon(image); 
     button.setActionCommand(Integer.toString(puzzle.getMyboard().getNewnumbers().get(i))); 
     button.addActionListener(sPanel.new ButtonActionListener()); 
     return button;  
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 

     count++; 
     set(this.imgsize[index]+1); //increase the size of the image 

     if (this.imgsize[index] < 64){ 

      ImageIcon image = new ImageIcon(this.images.getImagelist() 
       .get(index).getImage().getScaledInstance(this.imgsize[index], this.imgsize[index], Image.SCALE_SMOOTH)); 
      buttons[index].setIcon(image); 
      if (count > 24){ //reached final size 
       count = 0; //start counting again 
       index++; //move to the next image 
      } 
     }; 
     if (index == 10) timer.stop(); 
     repaint(); 

    } 

} 

私はそれを動作させるために必要なリソースのSSCCE与えられた量はそれほどそのために謝罪を提供することはできませんよ。

私の目標は、最初のアニメーションがそのプロセスの半分を終了したときに次のイメージのアニメーションを開始することです。したがって、2番目のイメージが半分のアニメーションに達すると、最初のイメージは完全なアニメーションを完了します。波の効果の種類。

改善できる点が他にもある場合は、提案を聞いてうれしいです。

更新:効果を達成するために使用される更新方法:

public void actionPerformed(ActionEvent e) { 

    count++; 
    this.imgsize[index]++; 

     ImageIcon image = new ImageIcon(this.images.getImagelist() 
      .get(index).getImage().getScaledInstance(this.imgsize[index], this.imgsize[index], Image.SCALE_SMOOTH)); 
     buttons[index].setIcon(image); 
     if (count > 24){ 
      count = 0; 
      index++; 
     } 
    if (count > 12 && index < 9) 
    { 
     this.imgsize[index+1]++; 
     image = new ImageIcon(this.images.getImagelist() 
       .get(index+1).getImage().getScaledInstance(this.imgsize[index+1], this.imgsize[index+1], Image.SCALE_SMOOTH)); 
      buttons[index+1].setIcon(image); 
    } 
    if (index == 10) timer.stop(); 
    repaint(); 

} 
+0

経験的アプローチとして考えるのではなく、その多くはタイムラインのようです。各画像はタイムラインに沿って開始点と終了点を持ち、タイムラインは可変長の時間を持つことができます。たとえば、2つの画像がある場合、最初の画像は0%から始まり75%で終了し、2番目の画像は50%から100%で終了します。その考え方は、各要素の進行をローカライズし、タイムラインを通る進行に基づいて、それ自身の局所的な時間枠に沿って進行の量を計算することです...単純な、ああ;) – MadProgrammer

+0

私のカウント変数タイムラインの進歩として? 0から始まり、25に達したら次のアニメーションを開始します.50が最初のアニメーションを完成すると、カウントが25ステップに達するたびに、次の要素のペアに移動できますか? –

+0

タイムラインは時間(0-1)の正規化されたコンセプトであり、画像はこのタイムラインに沿って異なる間隔(最初の画像では0 .0.75、2番目の画像では0.5-1.0)で動作を行います、あなたが2つの画像を持っているとき) – MadProgrammer

答えて

2

これは幾分過度に単純化されたアイデアである...

は基本的には、正規化されたタイムライン(0-1)イベントを設定しますそれに沿って、指定された点で開始し終了することができます。これらの期間中に何らかの「行動」が起こる可能性があります。

あなたの場合、これらのアクションはイメージスケーリングアクションで、そのスケールは特定のイベントが実行されている時間の割合に比例します。これは全体のタイムラインの割合です。

この

...すべてが素晴らしく混乱に聞こえるが、ことの利点があり、あなたがタイムラインの長さを変更することができ、コードの残りの部分は、例えば、自動的に

スケールします、あなたが取ることができます以上の10秒を実行し、

5秒以上を実行するためのタイムラインを生成し、あなたはヘクタールいませんでしたでしょう
timeline = new Timeline(events, 5000); 

にそれを変更するには、タイムラインを生成

timeline = new Timeline(events, 10000); 

1つのコード行を変更して動作させる。

あなたは画像のn数を供給することができますので、私はまた、自動的に一連の画像から、タイムラインのイベントを生成する方法を取り組んでいくつかの時間を費やしてきた、と彼らは

応じて互いに重なり合うように、それが必要なイベントを生成します

Example

さて、あなたはおそらくそれは、すべての変数だとあなたドン、これはすべての非常に複雑ですが、ポイントは、それはすべての変数、画像が縮小された持続時間、画像の数だ、であると考えています画像を追加/削除したり期間を変更したりするために多くの作業を行う必要がありません

Cavert - 私はこの例でgetScaledInstanceを使用しました、それは私も、利用可能なアニメーションフレームワークのいくつかを見て持ってお勧めする、高速でも、それは品質の画像

import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Image; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.UUID; 
import java.util.concurrent.TimeUnit; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test { 

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

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

        JFrame frame = new JFrame("Testing"); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        frame.add(new TestPane()); 
        frame.pack(); 
        frame.setLocationRelativeTo(null); 
        frame.setVisible(true); 
       } catch (IOException ex) { 
        ex.printStackTrace(); 
       } 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private Timeline timeline; 

     private Map<Object, Image> mapImages = new HashMap<>(5); 
     private List<Object> imageOrder = new ArrayList<>(5); 

     public TestPane() throws IOException { 
      BufferedImage[] images = new BufferedImage[]{ 
       ImageIO.read(new File("...")), 
       ImageIO.read(new File("...")), 
       ImageIO.read(new File("...")), 
       ImageIO.read(new File("...")) 
      }; 
      List<TimelineEvent> events = generateEvents(images, new ImageScaledObserver() { 
       @Override 
       public void imageScaled(Object id, Image image) { 
        if (!imageOrder.contains(id)) { 
         imageOrder.add(id); 
        } 
        mapImages.put(id, image); 
        repaint(); 
       } 
      }); 

      timeline = new Timeline(events, 10000); 
      Timer timer = new Timer(5, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        if (timeline.update()) { 
         ((Timer) e.getSource()).stop(); 
        } 
       } 
      }); 
      timer.setInitialDelay(5000); 
      timer.start(); 
     } 

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

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      for (Object id : imageOrder) { 
       Image image = mapImages.get(id); 
       int x = (getWidth() - image.getWidth(this))/2; 
       int y = (getHeight() - image.getHeight(this))/2; 
       g2d.drawImage(image, x, y, this); 
      } 
      g2d.dispose(); 
     } 

    } 

    protected List<TimelineEvent> generateEvents(BufferedImage[] images, ImageScaledObserver observer) { 
     double length = 1.0/(double) (images.length); 
     double overlap = length * 0.5; 
     List<TimelineEvent> events = new ArrayList<>(images.length); 
     double startAt = 0.0; 
     for (BufferedImage image : images) { 
      double endAt = Math.min(startAt + length + (overlap/2.0), 1.0); 
      events.add(new ScaleImageTimelineEvent(image, observer, startAt, endAt)); 
      startAt = Math.min(endAt - (overlap/2.0), 1.0); 
     } 
     return events; 
    } 

    public interface TimelineEvent { 

     public double[] range(); 

     public boolean isWithin(double timelineProgression); 

     public void performAction(double timelineProgression); 
    } 

    public abstract class AbstractTimelineEvent implements TimelineEvent { 

     private double from, to; 

     public AbstractTimelineEvent(double from, double to) { 
      this.from = from; 
      this.to = to; 
     } 

     @Override 
     public double[] range() { 
      return new double[]{from, to}; 
     } 

     @Override 
     public boolean isWithin(double timelineProgression) { 
      boolean within = timelineProgression >= from && timelineProgression <= to; 
      return within; 
     } 

     protected double localisedProgression(double timelineProgression) { 
      double max = from - to; 
      double value = timelineProgression - to; 
      double weight = value/max; 
      return 1d - weight; 
     } 

    } 

    public interface ImageScaledObserver { 

     public void imageScaled(Object id, Image img); 
    } 

    public class ScaleImageTimelineEvent extends AbstractTimelineEvent { 

     private BufferedImage original; 
     private ImageScaledObserver observer; 
     private UUID id; 

     public ScaleImageTimelineEvent(BufferedImage image, ImageScaledObserver observer, double from, double to) { 
      super(from, to); 
      this.original = image; 
      this.observer = observer; 
      this.id = UUID.randomUUID(); 
     } 

     @Override 
     public void performAction(double timelineProgression) { 
      double progress = localisedProgression(timelineProgression); 
      Image image = null; 
      if (progress < 1.0) { 
       int width = (int) (original.getWidth() * progress); 
       if (width > 0) { 
        image = original.getScaledInstance((int) (original.getWidth() * progress), -1, Image.SCALE_FAST); 
       } 
      } else { 
       image = original; 
      } 
      if (image != null) { 
       observer.imageScaled(id, image); 
      } 
     } 

    } 

    public static class Timeline { 

     private List<TimelineEvent> events; 

     private Long startTime; 
     private long duration; 

     public Timeline(List<TimelineEvent> events, long duration) { 
      this.events = events; 
      this.duration = duration; 
     } 

     public List<TimelineEvent> getEvents() { 
      return events; 
     } 

     public Long getStartTime() { 
      return startTime; 
     } 

     public long getDuration() { 
      return duration; 
     } 

     public void start() { 
      if (startTime == null) { 
       startTime = System.nanoTime(); 
      } 
     } 

     public void stop() { 
      startTime = null; 
     } 

     public boolean update() { 
      if (startTime == null) { 
       start(); 
      } 

      boolean completed = false; 

      long currentTime = System.nanoTime(); 
      long diff = currentTime - getStartTime(); 

      long nanoDuration = TimeUnit.NANOSECONDS.convert(getDuration(), TimeUnit.MILLISECONDS); 
      double progress = diff/(double) nanoDuration; 
      if (progress > 1.0d) { 
       progress = 1.0d; 
       completed = true; 
       stop(); 
      } 

      for (TimelineEvent evt : getEvents()) { 
       if (evt.isWithin(progress)) { 
        evt.performAction(progress); 
       } 
      } 
      return completed; 
     } 
    } 

} 

を生成しないでもないですこれは、地域性のような追加の機能を提供します。

この例では、UUIDを使用して、imageScaledイベントの一意の識別子を生成しています。 ScaleImageTimelineEventは、特定の画像にリンクされた自分の識別子を取得して、どの画像が拡大縮小されたかを判断し、より正確な更新を行うことができます。

関連する問題