【问题标题】:How to make an animated number counter using Java Swing?如何使用 Java Swing 制作动画数字计数器?
【发布时间】:2021-03-14 13:29:50
【问题描述】:

我想做一个动画数字计数器,像这样:

我希望能够输入值并通过动画更新计数器。

我可以从 Google 找到如何在 Android 上执行此操作,但我找不到任何有关如何在 Java Swing 中执行此操作的信息。我如何在 Swing 中制作这样的东西?

【问题讨论】:

  • 我不想这么说,但如果您对 Swing 足够熟悉来完成这项工作,您就不会问这个问题。我已经完成了大量与 Swing 相关的编程,但这仍然可能是一个挑战。我建议您查看动画图像显示的内容并尝试重复它的不同部分。首先,只显示数字。他们弄清楚如何上下旋转它们。然后让它们独立旋转。有很多事情需要考虑,所以只需将其分解并从不同方面着手。
  • 同意以上评论。但一般来说,任何动画都是使用Swing Timer 完成的。因此,您需要以某种方式为不同位置的数字绘画设置动画。这是一个进行水平滚动的基本示例:stackoverflow.com/questions/33907207/…。多位数字之间的垂直滚动会复杂得多。
  • 我创建了一个带有向上滑动数字的时钟。我创建了一个垂直排列的数字 0 - 9 的 BufferedImage。不幸的是,图片已从这篇归档文章中消失,Sliding Clock Using Java Swing
  • 这是“如何做”的问题。它不是针对场外资源征求建议,也不需要在此基础上关闭。

标签: java swing animation counter


【解决方案1】:

这不是一个完整的答案,但这是一个滑动 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();
            }
        }
        
    }

}

【讨论】:

    【解决方案2】:
    import java.awt.Dimension;
    import java.awt.Font;
    import java.awt.GridLayout;
    import java.awt.Point;
    
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    
    public class Animation {
        boolean loop=true;//true                            //loop
        static int start=1;//1                              //start
        static int end=10+1;//20                            // end + 1
        int delay1=1000;//1s                                // delay
        int delay2=1;//1ms                                  // delay
        Font font=new Font("Helvetica",Font.BOLD,25);       //Font
        
        Timer timer=new Timer(delay1, e -> move());JPanel panel = new JPanel();int[] size = {50,100};Point point = new Point(210,size[1]);
        Timer timer1=null;int value=start-1;int i;
        public static void main(String[] args) {if (start!=end) {new Animation();}}
        public void move() {
            timer.stop();value ++;
            if (!loop && value==end) {timer.stop();}i=0;
            timer1 = new Timer(delay2, e -> {
                if (i==100) {
                    timer1.stop();
                    timer.start();
                }
                point.setLocation(point.getX(), point.getY()-1);
                panel.setLocation(point);
                panel.revalidate();
                i++;
            });timer1.start();
            if (loop && value==end-1) {point.setLocation(point.getX(),size[1]+size[1]);value = start-1;}else if (value==end-1 && !loop){System.exit(0);}
        }
        public Animation() {
            JFrame frame = new JFrame();frame.setSize(500,300);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.add(panel);frame.setLocationRelativeTo(null);
            panel.setLocation(point);frame.setLayout(null);frame.revalidate();panel.setSize(new Dimension(size[0],size[1]*Math.abs(end-(start-1))));
            panel.setLayout(new GridLayout(Math.abs(end-start)+start,1));if (!(end-start<0)) {for (int i=start;i!=(end-start)+start;i++) {JLabel la = new JLabel(String.valueOf(i));la.setFont(font);panel.add(la);
            }}timer.start();frame.revalidate();frame.setVisible(true);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-09
      • 1970-01-01
      • 2013-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多