Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么我的动画圈的位置会闪烁?_Java_Swing_Animation_Trident - Fatal编程技术网

Java 为什么我的动画圈的位置会闪烁?

Java 为什么我的动画圈的位置会闪烁?,java,swing,animation,trident,Java,Swing,Animation,Trident,我用它制作了一个(看起来)简单的动画。许多圆通过正弦插值从下至上再向后移动: 动画本身似乎可以工作,但有一到两帧,我的所有球体都会闪烁到最上面的位置 为什么它会闪烁?谁在用看似错误的值调用setY方法 我制作了一个testclass来重现这种行为。您需要让它工作: import java.awt.BorderLayout; import java.awt.Color; import java.awt.FlowLayout; import java.awt.Graphics; import ja

我用它制作了一个(看起来)简单的动画。许多圆通过正弦插值从下至上再向后移动:

动画本身似乎可以工作,但有一到两帧,我的所有球体都会闪烁到最上面的位置

为什么它会闪烁?谁在用看似错误的值调用
setY
方法

我制作了一个testclass来重现这种行为。您需要让它工作:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JDialog;
import javax.swing.JPanel;

import org.pushingpixels.trident.api.Timeline;
import org.pushingpixels.trident.api.Timeline.RepeatBehavior;
import org.pushingpixels.trident.api.ease.TimelineEase;
import org.pushingpixels.trident.api.swing.SwingRepaintTimeline;

public class MovingSpheresTest extends JDialog {

    private final double sphereRadius = 3d;

    private final double sphereCount = 12d;

    private final double helixHeight = 100d;

    private final double size = 200d;

    private final double animationSpeed = 0.5d;

    private List<CenteredSphere> spheres;

    private SwingRepaintTimeline repaintTimeline;

    private final JPanel contentPanel = new JPanel() {
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            paintFrame((Graphics2D) g);
        }

        private void paintFrame(Graphics2D g) {
            Graphics2D create = (Graphics2D) g.create();
            try {
                create.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                create.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                create.setColor(Color.BLACK);
                for (CenteredSphere centeredSphere : spheres) {
                    create.fill(centeredSphere);
                }
            } finally {
                create.dispose();
            }
        }
    };

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        try {
            MovingSpheresTest dialog = new MovingSpheresTest();
            dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
            dialog.setVisible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Create the dialog.
     */
    public MovingSpheresTest() {
        setBounds(100, 100, 450, 300);
        getContentPane().setLayout(new BorderLayout());
        contentPanel.setLayout(new FlowLayout());
        getContentPane().add(contentPanel, BorderLayout.CENTER);
        installSpheres();
        installRepaintTimeline();
    }

    private void installSpheres() {
        double helixRadius = helixHeight / 2;
        double effectiveWidth = size - (2 * sphereRadius);
        double sphereDistance = effectiveWidth / (sphereCount - 1);
        double sphereCenterX = sphereRadius;
        double sphereCenterY = size / 2d;
        double sphereCenterYInitial = sphereCenterY - helixRadius;

        spheres = new ArrayList<>();
        for (int sphereIndex = 0; sphereIndex < sphereCount; sphereIndex++) {
            CenteredSphere sphere = new CenteredSphere(sphereCenterX, sphereRadius);
            spheres.add(sphere);
            sphereCenterX += sphereDistance;
            Timeline.builder()
                    .addPropertyToInterpolate(Timeline.<Double>property("y").on(sphere).from(sphereCenterYInitial)
                            .to(sphereCenterY + helixRadius))
                    .setEase(new FullSine((float) (sphereIndex * 2 * Math.PI / sphereCount)))
                    .setDuration((long) (animationSpeed * 3000d)).playLoop(RepeatBehavior.LOOP);
        }

    }

    private class FullSine implements TimelineEase {

        private float horizontalOffset;

        private FullSine(float horizontalOffset) {
            this.horizontalOffset = horizontalOffset;
        }

        @Override
        public float map(float durationFraction) {
            return ((float) Math.sin(durationFraction * Math.PI * 2f + horizontalOffset) + 1f) / 2f;
        }
    }

    private void installRepaintTimeline() {
        repaintTimeline = SwingRepaintTimeline.repaintBuilder(contentPanel).build();
        repaintTimeline.playLoop(RepeatBehavior.LOOP);
    }

    public class CenteredSphere extends Ellipse2D.Double {

        private double sphereCenterX;
        private double sphereRadius;

        public CenteredSphere(double sphereCenterX, double sphereRadius) {
            this.sphereCenterX = sphereCenterX;
            this.sphereRadius = sphereRadius;
        }

        public void setY(double y) {
            setFrameFromCenter(sphereCenterX, y, sphereCenterX + sphereRadius, y + sphereRadius);
        }
    }
}

导入java.awt.BorderLayout;
导入java.awt.Color;
导入java.awt.FlowLayout;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.RenderingHints;
导入java.awt.geom.Ellipse2D;
导入java.util.ArrayList;
导入java.util.List;
导入javax.swing.JDialog;
导入javax.swing.JPanel;
导入org.pushingpixels.trident.api.Timeline;
导入org.pushingpixels.trident.api.Timeline.RepeatBehavior;
导入org.pushingpixels.trident.api.ease.TimelineEase;
导入org.pushingpixels.trident.api.swing.swingrepaintline;
公共类MovingSpheresTest扩展JDialog{
私人最终双球体半径=3d;
专用最终双sphereCount=12d;
私人最终双螺旋高度=100d;
私人最终双尺寸=200d;
私人最终双动画速度=0.5d;
私人列表领域;
私有SwingrPaintTimeline重新绘制Timeline;
私有最终JPanel contentPanel=新JPanel(){
受保护组件(图形g){
超级组件(g);
画框((图2d)g);
}
专用void画框(Graphics2D g){
Graphics2D create=(Graphics2D)g.create();
试一试{
create.setRenderingHint(RenderingHints.KEY\u抗锯齿,RenderingHints.VALUE\u抗锯齿开);
create.setRenderingHint(RenderingHints.KEY\u RENDERING,RenderingHints.VALUE\u RENDER\u QUALITY);
create.setColor(Color.BLACK);
用于(中心球体中心球体:球体){
创建.填充(中心球体);
}
}最后{
create.dispose();
}
}
};
/**
*启动应用程序。
*/
公共静态void main(字符串[]args){
试一试{
MovingSphereTest对话框=新建MovingSphereTest();
setDefaultCloseOperation(JDialog.DISPOSE\u ON\u CLOSE);
对话框.setVisible(true);
}捕获(例外e){
e、 printStackTrace();
}
}
/**
*创建对话框。
*/
公共移动测试(){
立根(100100450300);
getContentPane().setLayout(新的BorderLayout());
setLayout(新的FlowLayout());
getContentPane().add(contentPanel,BorderLayout.CENTER);
安装球体();
installRepaitTimeline();
}
私有空间(){
双螺旋半径=螺旋高度/2;
双效宽度=尺寸-(2*球体半径);
双sphereDistance=有效宽度/(sphereCount-1);
双球体中心=球体半径;
双球体中心=尺寸/2d;
双球心初始=球心-螺旋半径;
spheres=新的ArrayList();
对于(int-sphereIndex=0;sphereIndex
如注释和固定

这很有趣。这是因为有一个基本假设,
TimelineEase
始终映射[0.0-1.0]区间,而不会“扭曲”端点。在这种特定情况下,在每个动画循环期间,将使用自定义
FullSine
基于球体偏移重新映射该间隔,但在循环重置期间,不会映射“端点”