需要帮助使用JavaFX在HBox中设置图像动画吗

需要帮助使用JavaFX在HBox中设置图像动画吗,java,arrays,javafx,javafx-8,Java,Arrays,Javafx,Javafx 8,我正在为一款名为《反击:全球进攻》的游戏创建一个模拟程序,我一直在研究如何在HBox中为某些图像制作动画。在游戏中,有一些武器箱,里面装着各种稀有的皮肤。单击“打开”按钮后,可能获胜的项目应开始在HBox中滚动。把它想象成命运之轮,它开始时很快,然后逐渐变慢,直到停在一个名字上,但在这种情况下,不是名字而是项目,我有一个水平的HBox,上面有滚动的图像。下面是一个很好的例子,说明了我的想法 目前,我有一个ImageView类的实例分配给每个单独的武器图像,这些图像应该包含在要滚动的项目的总组中,

我正在为一款名为《反击:全球进攻》的游戏创建一个模拟程序,我一直在研究如何在HBox中为某些图像制作动画。在游戏中,有一些武器箱,里面装着各种稀有的皮肤。单击“打开”按钮后,可能获胜的项目应开始在HBox中滚动。把它想象成命运之轮,它开始时很快,然后逐渐变慢,直到停在一个名字上,但在这种情况下,不是名字而是项目,我有一个水平的HBox,上面有滚动的图像。下面是一个很好的例子,说明了我的想法

目前,我有一个ImageView类的实例分配给每个单独的武器图像,这些图像应该包含在要滚动的项目的总组中,还有一个数组来保存所有这些图像。在GUI上,我设置了HBox的最大宽度和高度,这样从左到右放置在HBox内的任何3个图像都可以完美地填充其体积。我的第一个问题就在这里。如果我试着做类似的事情

Hbox.getChildren().addAll(itemArray); 
它将添加前3个很好,但将继续添加超出HBox边界的图像,直到到达主windows边界。有没有办法在HBox中添加比最大显示图像数更多的图像(由于我设置的当前HBox大小,图像数为3),同时防止图像超出HBox边界并隐藏在后面

第二个问题是,对我的HBox内的每个图像设置动画,使其向左滚动,而不是超出或超出HBox边框的最佳方式是什么?我需要最左边的图像从屏幕上向左滑动,中间的图像滑动到左侧位置,一个新图像从右侧滑入以填充右侧位置,并以逐渐减慢的速度重复此操作,直到落在某个项目上

当前,将此代码添加到“打开”按钮的事件处理程序会将item1、item2和item3中的图像正确添加到HBox中。但是如果我超过3个图像(例如,将HBox.addAll()设置为itemArray而不是单独设置前3个项目),它将超过HBox边框,并开始将它们放置在场景顶部,直到到达主窗口边框注意:ImageView类(item1-item15)总共有15个实例,但我将代码缩短为4个,将数组内容缩短为4个,因为无论何时将3个以上的图像放入HBox,问题都会发生

public class Controller
{
@FXML
private HBox hBox;

    public void openCaseAction(ActionEvent actionEvent)
        {
            final ImageView item1 = new ImageView(new Image(getClass().getResourceAsStream("../images/image1.png")));
            final ImageView item2 = new ImageView(new Image(getClass().getResourceAsStream("../images/image2.png")));
            final ImageView item3 = new ImageView(new Image(getClass().getResourceAsStream("../images/image3.png")));
            final ImageView item4 = new ImageView(new Image(getClass().getResourceAsStream("../images/image4.png")));

            final ImageView[] itemArray ={item1,item2,item3,item4};

            hBox.getChildren().addAll(item1,item2,item3);
    }
}

您可能希望为此使用自定义布局,而不是HBox。请看显示架示例:

  • 下载
  • 提取样本包
  • 运行demo/javafx_samples/Ensemble8.jar程序
  • 在程序的搜索栏中键入“Display Shelf”
  • 查看显示架示例UI和源代码
  • 在遵守原始许可条款的同时,根据需要进行复制和修改
  • 这并不完全是你想要的,但这将是一个比试图在HBox中设置项目动画更接近的起点

    Oracle DisplayShelf示例代码:

    /*
     * Copyright (c) 2008, 2014, Oracle and/or its affiliates.
     * All rights reserved. Use is subject to license terms.
     *
     * This file is available and licensed under the following license:
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     *  - Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *  - Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in
     *    the documentation and/or other materials provided with the distribution.
     *  - Neither the name of Oracle Corporation nor the names of its
     *    contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    package ensemble.samples.graphics2d.displayshelf;
    
    import javafx.animation.Interpolator;
    import javafx.animation.KeyFrame;
    import javafx.animation.KeyValue;
    import javafx.animation.Timeline;
    import javafx.beans.InvalidationListener;
    import javafx.beans.Observable;
    import javafx.collections.ObservableList;
    import javafx.event.EventHandler;
    import javafx.scene.Group;
    import javafx.scene.control.ScrollBar;
    import javafx.scene.image.Image;
    import javafx.scene.input.KeyCode;
    import javafx.scene.input.KeyEvent;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.layout.Region;
    import javafx.scene.shape.Rectangle;
    import javafx.util.Duration;
    
    /**
     * Simple 7 segment LED style digit. It supports the numbers 0 through 9.
     */
    /**
     * A ui control which displays a browse-able display shelf of images
     */
    public class DisplayShelf extends Region {
    
        private final Duration DURATION = Duration.millis(500);
        private final Interpolator INTERPOLATOR = Interpolator.EASE_BOTH;
        private final double SPACING = 50;
        private final double LEFT_OFFSET = -110;
        private final double RIGHT_OFFSET = 110;
        private final double SCALE_SMALL = 0.7;
        private PerspectiveImage[] items;
        private Group centered = new Group();
        private Group left = new Group();
        private Group center = new Group();
        private Group right = new Group();
        private int centerIndex = 0;
        private Timeline timeline;
        private ScrollBar scrollBar = new ScrollBar();
        private boolean localChange = false;
        private Rectangle clip = new Rectangle();
    
        public DisplayShelf(Image[] images) {
            // set clip
            setClip(clip);
            // set ids for styling via CSS
            setId("displayshelf");  
            scrollBar.setId("display-scrollbar");
            // create items
            items = new PerspectiveImage[images.length];
            for (int i = 0; i < images.length; i++) {
                final PerspectiveImage item =
                        items[i] = new PerspectiveImage(images[i]);
                final double index = i;
                item.setOnMouseClicked((MouseEvent me) -> {
                    localChange = true;
                    scrollBar.setValue(index);
                    localChange = false;
                    shiftToCenter(item);
                });
            }
            // setup scroll bar
            scrollBar.setMax(items.length - 1);
            scrollBar.setVisibleAmount(1);
            scrollBar.setUnitIncrement(1);
            scrollBar.setBlockIncrement(1);
            scrollBar.valueProperty().addListener((Observable ov) -> {
                if (!localChange) {
                    shiftToCenter(items[(int) Math.round(scrollBar.getValue())]);
                }
            });
            // create content
            centered.getChildren().addAll(left, right, center);
            getChildren().addAll(centered, scrollBar);
            // listen for keyboard events
            setFocusTraversable(true);
            setOnKeyPressed((KeyEvent ke) -> {
                if (ke.getCode() == KeyCode.LEFT) {
                    shift(1);
                    localChange = true;
                    scrollBar.setValue(centerIndex);
                    localChange = false;
                } else if (ke.getCode() == KeyCode.RIGHT) {
                    shift(-1);
                    localChange = true;
                    scrollBar.setValue(centerIndex);
                    localChange = false;
                }
            });
            // update
            update();
        }
    
        @Override
        protected void layoutChildren() {
            // update clip to our size
            clip.setWidth(getWidth());
            clip.setHeight(getHeight());
            // keep centered centered
            centered.setLayoutY((getHeight() - PerspectiveImage.HEIGHT) / 2);
            centered.setLayoutX((getWidth() - PerspectiveImage.WIDTH) / 2);
            // position scroll bar at bottom
            scrollBar.setLayoutX(10);
            scrollBar.setLayoutY(getHeight() - 25);
            scrollBar.resize(getWidth() - 20, 15);
        }
    
        private void update() {
            // move items to new homes in groups
            left.getChildren().clear();
            center.getChildren().clear();
            right.getChildren().clear();
            for (int i = 0; i < centerIndex; i++) {
                left.getChildren().add(items[i]);
            }
            center.getChildren().add(items[centerIndex]);
            for (int i = items.length - 1; i > centerIndex; i--) {
                right.getChildren().add(items[i]);
            }
            // stop old timeline if there is one running
            if (timeline != null) {
                timeline.stop();
            }
            // create timeline to animate to new positions
            timeline = new Timeline();
            // add keyframes for left items
            final ObservableList<KeyFrame> keyFrames = timeline.getKeyFrames();
            for (int i = 0; i < left.getChildren().size(); i++) {
                final PerspectiveImage it = items[i];
                double newX = -left.getChildren().size()
                        * SPACING + SPACING * i + LEFT_OFFSET;
                keyFrames.add(new KeyFrame(DURATION,
                        new KeyValue(it.translateXProperty(), newX, INTERPOLATOR),
                        new KeyValue(it.scaleXProperty(), SCALE_SMALL, INTERPOLATOR),
                        new KeyValue(it.scaleYProperty(), SCALE_SMALL, INTERPOLATOR),
                        new KeyValue(it.angle, 45.0, INTERPOLATOR)));
            }
            // add keyframe for center item
            final PerspectiveImage centerItem = items[centerIndex];
            keyFrames.add(new KeyFrame(DURATION,
                    new KeyValue(centerItem.translateXProperty(), 0, INTERPOLATOR),
                    new KeyValue(centerItem.scaleXProperty(), 1.0, INTERPOLATOR),
                    new KeyValue(centerItem.scaleYProperty(), 1.0, INTERPOLATOR),
                    new KeyValue(centerItem.angle, 90.0, INTERPOLATOR)));
            // add keyframes for right items
            for (int i = 0; i < right.getChildren().size(); i++) {
                final PerspectiveImage it = items[items.length - i - 1];
                final double newX = right.getChildren().size()
                        * SPACING - SPACING * i + RIGHT_OFFSET;
                keyFrames.add(new KeyFrame(DURATION,
                        new KeyValue(it.translateXProperty(), newX, INTERPOLATOR),
                        new KeyValue(it.scaleXProperty(), SCALE_SMALL, INTERPOLATOR),
                        new KeyValue(it.scaleYProperty(), SCALE_SMALL, INTERPOLATOR),
                        new KeyValue(it.angle, 135.0, INTERPOLATOR)));
            }
            // play animation
            timeline.play();
        }
    
        private void shiftToCenter(PerspectiveImage item) {
            for (int i = 0; i < left.getChildren().size(); i++) {
                if (left.getChildren().get(i) == item) {
                    int shiftAmount = left.getChildren().size() - i;
                    shift(shiftAmount);
                    return;
                }
            }
            if (center.getChildren().get(0) == item) {
                return;
            }
            for (int i = 0; i < right.getChildren().size(); i++) {
                if (right.getChildren().get(i) == item) {
                    int shiftAmount = -(right.getChildren().size() - i);
                    shift(shiftAmount);
                    return;
                }
            }
        }
    
        public void shift(int shiftAmount) {
            if (centerIndex <= 0 && shiftAmount > 0) {
                return;
            }
            if (centerIndex >= items.length - 1 && shiftAmount < 0) {
                return;
            }
            centerIndex -= shiftAmount;
            update();
        }
    }
    

    谢谢你的回复!这将非常有用。直到现在我才意识到类似DisplayShelf的东西存在,因为我一直在使用JavaFX Scene Builder 2.0来创建GUI。所以,除非我真的错过了什么,否则我在Scene Builder的任何地方都没有见过DisplayShelf哈哈。但是,在看了之后,如果我能够在没有滚动条的情况下设置它,并更改其属性,使它不会在图像居中时放大每个图像,而是从相同的距离显示它们,那么它可能会工作得很好。
    /*
     * Copyright (c) 2008, 2014, Oracle and/or its affiliates.
     * All rights reserved. Use is subject to license terms.
     *
     * This file is available and licensed under the following license:
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     *  - Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *  - Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in
     *    the documentation and/or other materials provided with the distribution.
     *  - Neither the name of Oracle Corporation nor the names of its
     *    contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    package ensemble.samples.graphics2d.displayshelf;
    
    import javafx.beans.property.DoubleProperty;
    import javafx.beans.property.SimpleDoubleProperty;
    import javafx.scene.Parent;
    import javafx.scene.effect.PerspectiveTransform;
    import javafx.scene.effect.Reflection;
    import javafx.scene.image.Image;
    import javafx.scene.image.ImageView;
    
    /**
     * A Node that displays a image with some 2.5D perspective rotation around the Y
     * axis.
     */
    public class PerspectiveImage extends Parent {
    
        private static final double REFLECTION_SIZE = 0.25;
    
        public static final double WIDTH = 200;
        public static final double HEIGHT = WIDTH + (WIDTH * REFLECTION_SIZE);
    
        private static final double RADIUS_H = WIDTH / 2;
        private static final double BACK = WIDTH / 10;
        private PerspectiveTransform transform = new PerspectiveTransform();
        /**
         * Angle Property
         */
        public final DoubleProperty angle = new SimpleDoubleProperty(45) {
            @Override
            protected void invalidated() {
                // when angle changes calculate new transform
                double lx = (RADIUS_H - Math.sin(Math.toRadians(angle.get())) * RADIUS_H - 1);
                double rx = (RADIUS_H + Math.sin(Math.toRadians(angle.get())) * RADIUS_H + 1);
                double uly = (-Math.cos(Math.toRadians(angle.get())) * BACK);
                double ury = -uly;
                transform.setUlx(lx);
                transform.setUly(uly);
                transform.setUrx(rx);
                transform.setUry(ury);
                transform.setLrx(rx);
                transform.setLry(HEIGHT + uly);
                transform.setLlx(lx);
                transform.setLly(HEIGHT + ury);
            }
        };
    
        public final double getAngle() {
            return angle.getValue();
        }
    
        public final void setAngle(double value) {
            angle.setValue(value);
        }
    
        public final DoubleProperty angleModel() {
            return angle;
        }
    
        public PerspectiveImage(Image image) {
            ImageView imageView = new ImageView(image);
            Reflection reflection = new Reflection();
            reflection.setFraction(REFLECTION_SIZE);
            imageView.setEffect(reflection);
            setEffect(transform);
            getChildren().addAll(imageView);
        }
    }