如何使用JavaSwing制作动画数字计数器?

gev0vcfq  于 2021-07-07  发布在  Java
关注(0)|答案(1)|浏览(437)

我想制作一个动画数字计数器,比如这个:

我想能够输入值,并有与动画计数器更新。
我可以从google上找到如何在android上实现这一点,但是我找不到任何关于如何在javaswing中实现这一点的信息。我怎样才能在秋千上做出这样的东西?

bvk5enib

bvk5enib1#

这不是一个完整的答案,但这是一个滑动jpanel的工作示例。可以修改此代码以在问题中创建显示。
下面是完整的可运行示例。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class SlidingDigitGUI implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new SlidingDigitGUI());
    }

    private SlidingPanel secondPanel;

    @Override
    public void run() {
        JFrame frame = new JFrame("Sliding Digit");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(createSlidingPanel(), BorderLayout.CENTER);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);

        Animation animation = new Animation();
        new Thread(animation).start();
    }

    public JPanel createSlidingPanel() {
        String[] digitValues = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };

        JPanel panel = new JPanel();
        panel.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 4, false));
        panel.setPreferredSize(new Dimension(300, 100));

        Font font = panel.getFont();
        Font derivedFont = font.deriveFont(Font.BOLD, 48F);

        secondPanel = new SlidingPanel(digitValues, derivedFont);
        secondPanel.setPanelValue("0");
        panel.add(secondPanel);

        return panel;
    }

    public class SlidingPanel extends JPanel {

        private static final long serialVersionUID = 661553022861652947L;

        private static final int MARGIN = 4;

        private int imageY;

        private BufferedImage slidingImage;

        private Dimension characterDimension;

        private final Font font;

        private String currentValue;

        private final String[] panelValues;

        public SlidingPanel(String[] panelValues, Font font) {
            this.panelValues = panelValues;
            this.font = font;
            this.characterDimension = calculateFontSize();
            this.slidingImage = generateSlidingImage();
            this.setPreferredSize(characterDimension);
        }

        private Dimension calculateFontSize() {
            int maxWidth = 0;
            int maxHeight = 0;
            FontRenderContext frc = new FontRenderContext(null, true, true);
            for (String s : panelValues) {
                Rectangle2D r2D = font.getStringBounds(s, frc);
                int rWidth = (int) Math.round(r2D.getWidth());
                int rHeight = (int) Math.round(r2D.getHeight());
                maxWidth = Math.max(maxWidth, rWidth);
                maxHeight = Math.max(maxHeight, rHeight);
            }

            return new Dimension(maxWidth, maxHeight);
        }

        private BufferedImage generateSlidingImage() {
            int height = calculateStringHeight() * (panelValues.length + 1);
            BufferedImage slidingImage = new BufferedImage(characterDimension.width, 
                    height, BufferedImage.TYPE_INT_RGB);
            Graphics g = slidingImage.getGraphics();
            g.setColor(Color.WHITE);
            g.fillRect(0, 0, characterDimension.width, height);
            g.setColor(Color.BLACK);
            g.setFont(font);

            int y = characterDimension.height - MARGIN;

            for (String s : panelValues) {
                g.drawString(s, 0, y);
                y += calculateStringHeight();
            }

            g.drawString(panelValues[0], 0, y);
            g.dispose();
            return slidingImage;
        }

        public void setPanelValue(String value) {
            int index = getValueIndex(value);
            this.currentValue = value;
            this.imageY = calculateStringHeight() * index;
            repaint();
        }

        public void updatePanelValue(String value) {
            if (!currentValue.equals(value)) {
                int index = getValueIndex(value);
                int finalY = calculateStringHeight() * index;
                SliderAnimation sliderAnimation = new SliderAnimation(imageY, finalY);
                new Thread(sliderAnimation).start();
                this.currentValue = value;
            }
        }

        private int getValueIndex(String value) {
            for (int index = 0; index < panelValues.length; index++) {
                if (value.equals(panelValues[index])) {
                    return index;
                }
            }

            return -1;
        }

        private int calculateStringHeight() {
            return characterDimension.height + MARGIN;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            BufferedImage subImage = slidingImage.getSubimage(0, imageY, 
                    characterDimension.width,
                    characterDimension.height);
            g.drawImage(subImage, 0, 0, this);
        }

        public class SliderAnimation implements Runnable {
            private int originalY;
            private int finalY;

            public SliderAnimation(int originalY, int finalY) {
                this.originalY = originalY;
                this.finalY = finalY;
            }

            @Override
            public void run() {
                int differenceY = finalY - originalY;
                if (finalY == 0) {
                    differenceY = characterDimension.height + MARGIN;
                }

                int steps = 10;
                double difference = (double) differenceY / steps;
                for (int index = 1; index <= steps; index++) {
                    imageY = (int) Math.round(difference * index + originalY);
                    update();
                    sleep(120L);
                }

                if (finalY == 0) {
                    imageY = 0;
                    update();
                } else {
                    imageY = finalY;
                }
            }

            private void update() {
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        SlidingPanel.this.repaint();
                    }
                });
            }

            private void sleep(long duration) {
                try {
                    Thread.sleep(duration);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    public class Animation implements Runnable {

        @Override
        public void run() {
            while (true) {
                update("3");
                sleep(2000L);
                update("8");
                sleep(2000L);
            }
        }

        private void update(final String value) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    secondPanel.updatePanelValue(value);
                }
            });
        }

        private void sleep(long duration) {
            try {
                Thread.sleep(duration);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

}

相关问题