2017-04-21 184 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