2015-11-11 2 views
0

Я работаю над созданием симуляционной программы для игры Counter-Strike: Global Offensive, и я зациклился на том, как мне оживить определенные изображения внутри HBox. В игре есть вещи с оружием, содержащие различные скины разной редкости. После нажатия кнопки «Открыть» возможные элементы для победы должны начинать прокрутку через HBox. Подумайте об этом почти так же, как Wheel of Fortune, где он начинается быстро и постепенно замедляется, пока он не остановится на 1 имя, но в этом случае вместо имен есть предметы, а вместо «колеса» у меня есть горизонтальный HBox с прокрутки изображений. Вот хороший пример того, что я пытаюсь сделать: http://cases.goaggro.com/.Нужна помощь Анимация изображений в HBox с использованием JavaFX

В настоящее время у меня есть экземпляр класса ImageView, назначенного каждому отдельному изображению оружия, которое должно быть включено в общую группу элементов, подлежащих прокатке, и массив для хранения всех этих изображений. В графическом интерфейсе я устанавливаю максимальную ширину и высоту HBox, чтобы любые 3 из этих изображений, помещенных внутри HBox слева направо, полностью заполняли его объем. Моя первая проблема здесь. Если я пытаюсь сделать что-то вроде

Hbox.getChildren().addAll(itemArray); 

это добавит первые три просто отлично, но будет продолжать добавлять изображения за пределами границ HBox до достижения границы главного окна. Есть ли способ добавить больше изображений в HBox, чем максимальное количество отображаемых изображений (3 из-за текущего размера HBox, который я установил), не позволяя им превышать границы HBox и просто скрываться в спине?

Второй вопрос: какой лучший способ сделать анимацию каждого изображения внутри моего HBox так, чтобы он прокручивался влево, но не за пределы или за пределами границ HBox? Мне нужно самое левое изображение для слайда слева от экрана, в то время как среднее изображение скользит влево, а новое изображение сместится справа, чтобы заполнить нужную позицию, и повторите это со скоростью, которая постепенно замедляется до пункт посадки по предмету.

В настоящее время добавление этого кода в обработчик событий кнопки «Открыть» добавляет изображения в элементы item1, item2 и item3 правильно в HBox. Но если я превысил 3 изображения (например, вместо HART-файла .addAll() вместо itemArray вместо первых 3-х элементов), он превышает границу HBox и начинает укладывать их поверх сцены до достижения главной границы окна. ПРИМЕЧАНИЕ: В общей сложности 15 экземпляров класса ImageView (item1-item15), но я сократил код до 4, а также содержимое массивов для этих 4, поскольку проблема возникает независимо от того, когда происходит более трех изображений помещаются в 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. Взгляните на пример дисплея:

  1. Загрузить Java 8 demos and samples from Oracle.
  2. Извлечь образец.
  3. Запустите программу demo/javafx_samples/Ensemble8.jar.
  4. Напечатайте панель «Display Shelf» в строке поиска программы.
  5. Просмотрите пример интерфейса дисплея и его исходный код.
  6. Скопируйте и измените так, как вы сочтете нужным, соблюдая первоначальные условия лицензии.

Это не будет именно то, что вы ищете, но это будет гораздо более близкая исходная точка, чем попытка анимировать элементы в HBox.

display shelf

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

/* 
* 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 для создания графического интерфейса. Поэтому, если я серьезно не пропустил что-то, я не видел DisplayShelf в любом месте Scene Builder haha. Однако, посмотрев на это, он может работать отлично, если я могу настроить его без полосы прокрутки и изменить его свойства, чтобы он не приближался к каждому изображению по мере того, как они центрировали себя, а показывали все из них расстояние. – r00tsh3ll

Смежные вопросы