2015-11-11 30 views
0

我正在爲一款叫做Counter-Strike:Global Offensive的遊戲創建一個模擬程序,而且我一直在關注如何在HBox中爲某些圖像製作動畫。在遊戲中,有包含各種不同稀有皮膚的武器箱。點擊「打開」按鈕後,可能的項目應該開始滾動瀏覽HBox。想象它幾乎就像命運之輪,它開始快速並逐漸減速,直到它停在一個名字上,但在這種情況下,而不是名稱有項目,而不是一個「輪子」,我有一個水平HBox與圖像滾動瀏覽。這是我想要製作的一個很好的例子:http://cases.goaggro.com/需要幫助使用JavaFX在HBox中設置動畫圖像

目前,我有一個ImageView類的實例,分配給每個武器圖像,應該包含在要滾動的全部項目組中,以及一個數組來保存所有這些圖像。在GUI上,我設置了HBox的最大寬度和高度,以便這些圖像中的任何一個從左到右放置在HBox內,完美地填充了它的「音量」。我的第一個問題在於此。如果我試圖做類似

Hbox.getChildren().addAll(itemArray); 

它會增加前3個蠻好的,但將繼續增加超出HBox中的邊界圖像,直到到達主窗口邊框。是否有任何方法可以將HBox中的圖像添加到最大顯示圖像數量(由於當前設置的HBox尺寸爲3),同時防止它們超出HBox邊界並僅隱藏在背面?

第二個問題是,什麼是最好的方式去動畫我的HBox內的每個圖像,以便滾動向左但不超出或超出HBox邊界?我需要將最左側的圖像從屏幕上向左滑動,而將中間的圖像滑動到左側的位置,然後從右側滑入新的圖像以填充正確的位置,然後以逐漸減慢速度物品着陸點。

當前,將此代碼添加到「打開」按鈕的事件處理函數中,將item1,item2和item3中的圖像正確添加到HBox中。但是,如果我超過3張圖像(例如將HBox .addAll()設置爲itemArray而不是前3個項目),它會超過HBox邊界,並開始將它們放置在場景的頂部,直至到達主窗口邊界。 注意:總共有15個ImageView類的實例(item1-item15),但我將代碼縮短爲只有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); 
    } 
} 

回答

1

您可能想爲此使用自定義佈局而不是HBox。看看Display Rack示例:

  1. 下載Java 8 demos and samples from Oracle
  2. 提取樣本包。
  3. 運行demo/javafx_samples/Ensemble8.jar程序。
  4. 在程序的搜索欄中輸入「Display Shelf」。
  5. 查看顯示器架示例UI和源代碼。
  6. 複製並修改您認爲合適的同時尊重原始許可條款。

它不會是你正在尋找的東西,但它會比嘗試在HBox中設置動畫項目更接近起點。

display shelf

甲骨文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(); 
    } 
} 

/* 
* 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); 
    } 
} 
+0

感謝您的答覆!這將是非常有用的。直到現在我還沒有意識到像DisplayShelf這樣的東西,因爲我一直在使用JavaFX Scene Builder 2.0來創建GUI。所以除非我嚴重遺漏某些東西,否則我在Scene Builder的任何地方都沒有看到DisplayShelf哈哈。雖然看過它,但如果我能夠在沒有滾動條的情況下進行設置,它可以很好地工作,並且可以改變它的屬性,以便它們不會放大每個圖像,因爲它們居中對齊,而是全部顯示它們距離。 – r00tsh3ll