按组Java Swing设置图像列表动画

按组Java Swing设置图像列表动画,java,swing,animation,Java,Swing,Animation,当前,我的代码将从列表中的图像从初始大小设置为最终大小,并继续设置下一个图像,直到完成所有图像的动画设置,并且所有图像都具有最终大小 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

当前,我的代码将从列表中的图像从初始大小设置为最终大小,并继续设置下一个图像,直到完成所有图像的动画设置,并且所有图像都具有最终大小

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();

    }

}
packageui;
导入java.awt.Dimension;
导入java.awt.GridLayout;
导入java.awt.Image;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入javax.swing.ImageIcon;
导入javax.swing.JButton;
导入javax.swing.JPanel;
导入javax.swing.Timer;
导入utils.SudokuGen;
//TODO:自动生成的Javadoc
/**
*类按钮面板。
*/
公共类ButtonPanel扩展JPanel实现ActionListener{
/**常量serialVersionId*/
私有静态最终长serialVersionUID=1L;
/**按钮*/
私有JButton[]按钮;
私有int[]imgsize;
私有int索引,计数;
私人定时器;
私有图像按钮图像;
私有静态最终整数计数=10;
私有静态final int INITSIZE=32;
私有静态final int COLUMNS=1;
私有静态最终整数行=9;
/**
*实例化一个新的按钮面板。
*
*@param拼图数独矩阵对象
*@param images图像对象
*@param sPanel数独游戏
*/
公共按钮面板(SudokuGen拼图、ImageButton图像、SudokuGen拼板){
//创建一个包含9个元素的JButton数组
this.buttons=newjbutton[puzzle.getMyboard().getNewnumbers().size()];
这个。图像=图像;
this.imgsize=新整数[计数];
对于(int i=0;i 24){
计数=0;
索引++;
}   
如果(计数>12&&索引<9)
{
this.imgsize[index+1]++;
image=newImageIcon(this.images.getImagelist()
.get(index+1).getImage().getScaleInstance(this.imgsize[index+1],this.imgsize[index+1],Image.SCALE_-SMOOTH));
按钮[索引+1]。设置图标(图像);
}
如果(索引==10)timer.stop();
重新油漆();
}

这是一个过于简化的想法

基本上,它建立了一个标准化的时间线(0-1),事件可以沿着时间线发生,从指定的点开始和结束。在这些“时间段”中,可能会发生一些“动作”

在您的案例中,这些操作是图像缩放操作,其缩放比例是给定事件已运行时间的比例,是整个时间线的比例

这听起来非常令人困惑,但其好处是,您可以更改时间线的持续时间,其余代码将自动缩放

例如,你可以采取

timeline = new Timeline(events, 10000);
它会生成一个时间线,运行超过10秒,并将其更改为

timeline = new Timeline(events, 5000);
这将生成一个运行时间超过5秒的时间线,并且您不必更改一行代码即可使其正常工作

我还花了一些时间研究如何从一系列图像中自动生成时间线事件,这样您就可以提供
n
数量的图像,它将生成所需的事件,以便它们相应地相互重叠

现在,你可能认为这太复杂了,但关键是,这都是可变的,图像缩放的持续时间,图像的数量,都是可变的,你不需要做很多事情来添加/删除图像或更改持续时间

Cavert-我在本例中使用了
GetScaleInstance
,它既不快速,也不能生成高质量的图像

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;
        }
    }

}
导入java.awt.Dimension;
导入java.awt.EventQueue;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.Image;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.image.buffereImage;
导入java.io.File;
导入java.io.IOException;
导入java.util.ArrayList;
导入java.util.HashMap;
导入java.util.List;
导入java.util.Map;
导入java.util.UUID;
导入java.util.concurrent.TimeUnit;
导入javax.imageio.imageio;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.Timer;
导入javax.swing.UIManager;
导入javax.swing.UnsupportedLookAndFeelException;
公开课考试{
公共静态void main(字符串[]args){
新测试();
}
公开考试(){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(ClassNotFoundException |实例化Exception | IllegalacessException |不支持ookandfeelException ex){
例如printStackTrace();
}
JFrame=新JFrame(“测试”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(newtestpane());
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
}捕获(IOEX异常){
例如printStackTrace();
}
}
});
}
公共类TestPane扩展了JPanel{
私人时间表;
私有映射mapImages=newhashmap(5);
私有列表imageOrder=新的ArrayList(5);
公共TestPane()引发IOException{
BuffereImage[]图像=新的BuffereImage[]{
ImageIO.read(新文件(“…”),
ImageIO.read(新文件(“…”),
ImageIO.read(新文件(“…”),
ImageIO.read(新文件(“…”)
};
List events=generateEvents(图像,新图像缩放的观察服务器(){
@凌驾
public void imageScaled(对象id、图像){
如果(!imageOrder.contains(id)){
imageOrder.add(id);
}
mapI
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;
        }
    }

}