Простой способ создания анимированного JScrollPane в Java?

В настоящее время у меня есть JScrollPane, который содержит в основном список элементов. Этот JScrollPane должен отображаться на информационном экране.

То, что я ищу, - это какой-то способ заставить его автоматически прокручиваться к нижней части списка с заданным интервалом, а затем возвращаться к началу. Я понимаю, что это, вероятно, недостижимо с помощью JScrollPane, поэтому любые предложения по альтернативам также были бы замечательными!


person user2064849    schedule 24.03.2013    source источник
comment
безопаснее будет двигаться с JScrollBar, возможно, придется изменить scroll_increment для этой работы, понятия не имею, что такое список элементов, нет проблем с JComponents, которые реализуют прокрутку, но прокрутка с помощью JPanel contians JComponents не может быть естественным...   -  person mKorbel    schedule 25.03.2013


Ответы (2)


Обычно я использую TimeingFramework, или вы можете использовать что-то вроде Trident или Unviversal 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();
            }
        }
    }
}
person MadProgrammer    schedule 25.03.2013

Вы изучали использование таймера для отправки инструкций прокрутки в JScrollPane через определенные промежутки времени? Просто первое, что приходит на ум...

person arcy    schedule 24.03.2013