2017-04-21 137 views
0

我有一个ImageView,我将其添加到TilesPane布局。我想将ImageView从指定的(x,y)位置动画到它将添加到的位置。将动画节点转换为布局

我想是这样的:

TilePane tp = new TilePane(); 

... 

ImageView iv = new ImageView(img); 
tp.getChildren().add(iv); 

TranslateTransition tt = new TranslateTransition(Duration.seconds(5), iv); 
tt.setFromX(0); 
tt.setFromY(0); 
tt.setToX(iv.x); 
tt.setToY(iv.y); 
tt.play(); 

但我得到这个错误:error: x has private access in ImageView

我试图这样做:

  1. 图像添加到TilePane布局。
  2. 获取图像位置。
  3. 将图像从指定的(x,y)位置动画到其当前位置。

如果这不是正确的/最好的方法来做到这一点,有什么选择?如果是这样,我该如何解决这个错误?

+0

请出示[所有相关的代码(HTTPS: //stackoverflow.com/help/mcve)和一个完整的堆栈跟踪(如果有的话)。你不说你是怎么做的“2.获取图片位置。” – jewelsea

+0

@jewelsea分别使用'iv.x'和'ix.y'作为x和y坐标 – sudoman

+0

哦,我明白了,那不会编译。您需要[生成布局传递](http://stackoverflow.com/questions/26152642/get-the-height-of-a-node-in-javafx-generate-a-layout-pass)来确定哪里节点将在其layoutX和layoutY值设置后结束,然后设置为源位置与布局位置的负差。您不指定源位置的坐标系。也许如果你使用场景坐标和sceneToLocal。只是有些想法,也许我会试试看。 – jewelsea

回答

2

这是我想出了,它类似于Fabian的答案,所以不会增加太多。起点随机计算,并在场景坐标中,然后通过sceneToLocal函数转换为本地坐标。

出于某种原因(我不明白)tilePane上的布局传递请求似乎没有工作,直到显示舞台后(显示舞台之前tilePane的高度和宽度将显示为0)。所以我在尝试做任何计算和动画之前先展示舞台。

鱼随机起始位置:

randomstart

鱼平铺学校动画后:

ordered finish

import javafx.animation.*; 
import javafx.application.Application; 
import javafx.geometry.*; 
import javafx.scene.Group; 
import javafx.scene.Node; 
import javafx.scene.Scene; 
import javafx.scene.image.*; 
import javafx.scene.layout.TilePane; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

import java.util.*; 
import java.util.stream.Collectors; 

public class Layup extends Application { 

    private final Random random = new Random(42); 

    // image license: linkware - backlink to http://www.fasticon.com 
    private static final String[] IMAGE_LOCS = { 
      "http://icons.iconarchive.com/icons/fasticon/fish-toys/128/Blue-Fish-icon.png", 
      "http://icons.iconarchive.com/icons/fasticon/fish-toys/128/Red-Fish-icon.png", 
      "http://icons.iconarchive.com/icons/fasticon/fish-toys/128/Yellow-Fish-icon.png", 
      "http://icons.iconarchive.com/icons/fasticon/fish-toys/128/Green-Fish-icon.png" 
    }; 

    @Override 
    public void start(Stage stage) throws Exception { 
     TilePane tilePane = createTilePane(IMAGE_LOCS); 

     Scene scene = new Scene(new Group(tilePane)); 

     stage.setScene(scene); 
     stage.show(); 
     stage.setTitle("Click on the scene to animate"); 

     animateIn(tilePane); 

     scene.setOnMouseClicked(event -> animateIn(tilePane)); 
    } 

    private TilePane createTilePane(String[] imageLocs) { 
     TilePane tilePane = new TilePane(10, 10); 
     tilePane.setPrefColumns(2); 

     Arrays.stream(imageLocs).map(
       loc -> new ImageView(new Image(
         loc, 64, 0, true, true 
       )) 
     ).collect(Collectors.toCollection(tilePane::getChildren)); 

     tilePane.setPadding(new Insets(200)); 
     return tilePane; 
    } 

    private void animateIn(TilePane tilePane) { 
     // layout tilePane 
     tilePane.applyCss(); 
     tilePane.layout(); 

     double W = (int) tilePane.getScene().getWidth(); 
     double H = (int) tilePane.getScene().getHeight(); 

     ParallelTransition pt = new ParallelTransition(); 

     for (int i = 0; i < IMAGE_LOCS.length; i++) { 
      Node child = tilePane.getChildren().get(i); 

      Point2D start = new Point2D(
        random.nextInt((int) (W - child.getBoundsInLocal().getWidth())), 
        random.nextInt((int) (H - child.getBoundsInLocal().getHeight())) 
      ); 

      Point2D startInLocal = child.sceneToLocal(start); 

      TranslateTransition tt = new TranslateTransition(Duration.seconds(.5), child); 
      tt.setFromX(startInLocal.getX()); 
      tt.setFromY(startInLocal.getY()); 
      tt.setToX(0); 
      tt.setToY(0); 

      pt.getChildren().add(tt); 
     } 

     pt.play(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
+0

最近一段时间的答复(抱歉),我真的很想接受你的答案,它缺少一件事,我们如何才能让鱼从同一个位置开始? – sudoman

+1

如果您希望所有内容都从相同位置开始,则只需使用StackPane而不是TilePane。我只是使用了TilePane,因为这是你在问题中使用的,所以我假设你想让这些项目从平铺位置开始。 – jewelsea

1

最终位置将由布局合格后的layoutXlayoutY属性决定。此外,任何转换都与该位置有关,所以(0, 0)需要是转换的最终值。

private static final double START_X = 50; 
private static final double START_Y = 50; 

@Override 
public void start(Stage primaryStage) { 
    TilePane tilePane = new TilePane(); 
    tilePane.setPrefSize(200, 200); 
    Image image = new Image("https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-icon.png", 50, 50, true, false); 
    Button btn = new Button("add"); 
    btn.setOnAction((ActionEvent event) -> { 
     ImageView img = new ImageView(image); 
     tilePane.getChildren().add(img); 

     // layout tilePane 
     tilePane.applyCss(); 
     tilePane.layout(); 

     // create transition from start position to final position 
     TranslateTransition transition = new TranslateTransition(Duration.seconds(4), img); 
     transition.setFromX(START_X - img.getLayoutX()); 
     transition.setFromY(START_Y - img.getLayoutY()); 
     transition.setToX(0); 
     transition.setToY(0); 

     transition.play(); 
    }); 

    VBox root = new VBox(btn, tilePane); 

    Scene scene = new Scene(root); 

    primaryStage.setScene(scene); 
    primaryStage.show(); 
} 
+0

它并不是真的那种我正在寻找的东西,图像不是从指定的位置开始,而是需要从场景中的坐标开始。它仍然相对于图像本身 – sudoman