代码之家  ›  专栏  ›  技术社区  ›  user3323950

如何设置圆的动画

  •  1
  • user3323950  · 技术社区  · 10 年前

    我正在学习Java中的GUI。我正在制作一个非常简单的GUI,它每5毫秒就缩放一次圆圈的大小,然后一旦宽度和高度达到某个数字,它就会缩小,并继续执行这个过程。我设法使圆圈出现在屏幕上,但由于某种奇怪的原因,它没有缩放。

    public class circle extends JPanel implements ActionListener {
    
    
    
        Timer tm = new Timer(5, this);
    
        int XDiameter = 20;
        int YDiameter = 20;
    
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
    g.setColor(Color.GREEN);
            g.fillOval(40, 40, XDiameter, YDiameter);
    
            tm.start();
        }
    
    
    
        @Override
        public void actionPerformed(ActionEvent e) {
    
            SuperSizeCircle();
            repaint();
    
        }
    
        public void SuperSizeCircle(){
            while(true){
                XDiameter = XDiameter + 2;
                YDiameter = YDiameter + 2;
                if(XDiameter > 200 && YDiameter > 200){
                    XDiameter --;
                    YDiameter --;
                }else if(XDiameter < 20 && YDiameter < 20){
                XDiameter ++;
                YDiameter ++;
            }
            }
        }
    
    }
    

    主要类别:

    public class main {
    
    
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        JFrame frame = new JFrame("Circle enlarger");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400,400);
        frame.setVisible(true);
    
        circle co = new circle();
        frame.add(co);
    
    }
    

    }

    2 回复  |  直到 10 年前
        1
  •  2
  •   Paul Samsotha    10 年前
    1. 这个 while(true) 从不擅长 Swing 动画把它扔出窗外,永远告别它。把它从你的方法中去掉。你不需要它。计时器负责 “循环”

    2. 不要启动 Timer paintComponent 方法在构造函数中执行。

    3. 您应该通过将代码包装在 SwingUtilities.invokeLater.. 看见 Initial Threads 了解更多详情。

    4. 您应该将框架设置为可见 之后 添加所有组件。

    5. if 在您的 SuperSizeCircle() 如果你从逻辑上看,你会把彼此搞得一团糟。这就是为什么你需要不断补充。我觉得这并不正确。相反,我们使用一个标志(布尔值)来确定它应该增长还是收缩

      boolean grow = true;
      
      public void SuperSizeCircle() {
      
          if (XDiameter >= 200) {
              grow = false;
          }
          if (XDiameter <= 20) {
              grow = true;
          }
      
          if (grow) {
              XDiameter += 2;
              YDiameter += 2;
          } else {
              XDiameter -= 2;
              YDiameter -= 2;
          }
      }
      

    enter image description here

    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    
    public class CirclePanel extends JPanel implements ActionListener {
    
        Timer tm = new Timer(15, this);
    
        boolean grow = true;
    
        int XDiameter = 20;
        int YDiameter = 20;
    
        public CirclePanel() {
            tm.start();
        }
    
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.GREEN);
            g.fillOval(50, 50, XDiameter, YDiameter);
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
    
            SuperSizeCircle();
            repaint();
    
        }
    
        public void SuperSizeCircle() {
    
            if (XDiameter >= 200) {
                grow = false;
            }
            if (XDiameter <= 20) {
                grow = true;
            }
    
            if (grow) {
                XDiameter += 3;
                YDiameter += 3;
            } else {
                XDiameter -= 3;
                YDiameter -= 3;
            }
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    JFrame frame = new JFrame("Circle enlarger");
                    CirclePanel co = new CirclePanel();
                    frame.add(co);
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setSize(300, 300);
                    frame.setVisible(true);
                }
            });
        }
    }
    
        2
  •  1
  •   jewelsea    10 年前

    这里有一个 JavaFX 基于解决方案,仅用于变化。

    small big

    import javafx.animation.ScaleTransition;
    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.layout.StackPane;
    import javafx.scene.paint.Color;
    import javafx.scene.shape.Circle;
    import javafx.stage.Stage;
    import javafx.util.Duration;
    
    public class CircleScaler extends Application {
    
        private static final double MIN_RADIUS = 10;
        private static final double MAX_RADIUS = 100;
        private static final double PANE_SIZE  = 2 * (MIN_RADIUS + MAX_RADIUS);
        private static final double SCALE_FACTOR = MAX_RADIUS / MIN_RADIUS;
        private static final Duration SCALE_DURATION = Duration.seconds(3);
    
        @Override
        public void start(Stage stage) {
            final Circle circle = new Circle(MIN_RADIUS, Color.CRIMSON);
    
            final StackPane root = new StackPane(circle);
            root.setPrefSize(PANE_SIZE, PANE_SIZE);
    
            stage.setScene(new Scene(root, Color.PALETURQUOISE));
            stage.show();
    
            animateCircle(circle);
        }
    
        private void animateCircle(Circle circle) {
            ScaleTransition scaler = new ScaleTransition(
                    SCALE_DURATION,
                    circle
            );
            scaler.setFromX(1);
            scaler.setToX(SCALE_FACTOR);
            scaler.setFromY(1);
            scaler.setToY(SCALE_FACTOR);
    
            scaler.setAutoReverse(true);
            scaler.setCycleCount(ScaleTransition.INDEFINITE);
            scaler.play();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    有关JavaFX中更复杂的动画圆圈,请参见 james-d's animation of 300 balls .