在Java中创建动画JScrollPane的简单方法?

时间:2013-03-24 21:44:40

标签: java swing animation jscrollpane jscrollbar

我目前有一个JScrollPane,它基本上包含了一个项目列表。此JScrollPane将显示在信息屏幕上。

我正在寻找的是某种方式让它以给定的间隔自动滚动到列表的底部,然后回到顶部。我认识到使用JScrollPane可能无法实现这一点,因此任何替代方案的建议都会很棒!

2 个答案:

答案 0 :(得分:1)

通常我会使用TimingFramework,或者您可以使用TridentUnviversal Tween Engine之类的内容作为任何动画的基础。主要原因是,除了为您完成大部分工作外,它们还提供可变速度,这将使动画看起来更自然。

但是你可以使用javax.swing.Timer来实现基本概念。

此示例允许您滚动到图像的底部然后再返回。

动画需要5秒钟(由runningTiming变量提供),允许它变化(图像越大,移动越快,图像越小,速度越慢)。

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class AutoScroller {

    public static void main(String[] args) {
        new AutoScroller();
    }
    private long startTime = -1;
    private int range = 0;
    private int runningTime = 5000;
    private int direction = 1;

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

                final JScrollPane scrollPane = new JScrollPane(new TestPane());

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(scrollPane);
//                frame.pack();
                frame.setSize(scrollPane.getPreferredSize().width, 200);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                Timer timer = new Timer(40, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        if (startTime < 0) {
                            startTime = System.currentTimeMillis();
                            range = scrollPane.getViewport().getView().getPreferredSize().height - scrollPane.getHeight();
                        }
                        long duration = System.currentTimeMillis() - startTime;
                        float progress = 1f;
                        if (duration >= runningTime) {
                            startTime = -1;
                            direction *= -1;
                            // Make the progress equal the maximum range for the new direction
                            // This will prevent it from "bouncing"
                            if (direction < 0) {
                                progress = 1f;
                            } else {
                                progress = 0f;
                            }
                        } else {
                            progress = (float) duration / (float) runningTime;
                            if (direction < 0) {
                                progress = 1f - progress;
                            }
                        }

                        int yPos = (int) (range * progress);

                        scrollPane.getViewport().setViewPosition(new Point(0, yPos));

                    }
                });
                timer.setRepeats(true);
                timer.setCoalesce(true);
                timer.start();

            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage image;

        public TestPane() {
            try {
                image = ImageIO.read(new File("Path/to/your/image"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return image == null ? new Dimension(200, 200) : new Dimension(image.getWidth(), image.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (image != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                int x = (getWidth() - image.getWidth()) / 2;
                int y = (getHeight() - image.getHeight()) / 2;
                g2d.drawImage(image, x, y, this);
                g2d.dispose();
            }
        }
    }
}

答案 1 :(得分:0)

您是否考虑过使用计时器每隔一段时间向JScrollPane发送滚动指令?只是想到的第一件事......