2013-07-02 21 views
6

如果你看下面的測試,你會看到所有的圈子四處移動,而不是僅僅添加一個新的圈子。它不會每次都發生。我認爲只有當新孩子超出現有範圍時纔會這樣。但是我怎樣才能得到它,以便在添加另一個圓時不管我放置圓的位置如何都不會移動組和小組的所有子項?如何在添加子項時使JavaFX組無法移動?

請注意,如果我沒有設置組的規模,他們不會全部移動。所以它與設置比例有關。

import javafx.application.*; 
import javafx.beans.value.*; 
import javafx.collections.*; 
import javafx.scene.*; 
import javafx.scene.layout.*; 
import javafx.scene.shape.*; 
import javafx.stage.*; 

import java.util.*; 


public class GroupTest extends Application { 
    public static void main(String[] args) { 
     launch(args); 
    } 

    public void start(Stage stage) { 
     Pane pane = new Pane(); 

     Group root = new Group(); 
     // NOTE: removing these two setScale* lines stops the undesirable behavior 
     root.setScaleX(.2); 
     root.setScaleY(.2); 
     root.setTranslateX(100); 
     root.setTranslateY(100); 

     root.layoutXProperty().addListener(new ChangeListener<Number>() { 
      @Override 
      public void changed(ObservableValue<? extends Number> observableValue, Number number, Number number2) { 
       System.out.println("root layout: " + root.getLayoutX() + ", " + root.getLayoutY()); 
      } 
     }); 

     root.getChildren().addListener(new ListChangeListener<Node>() { 
      @Override public void onChanged(Change<? extends Node> change) { 
       System.out.println("root: " + root.getBoundsInParent()); 
       System.out.println("root: " + root.getBoundsInLocal()); 
       System.out.println("root: " + root.getLayoutBounds()); 
       System.out.println("root: " + root.getLayoutX() + ", " + root.getLayoutY()); 
      } 
     }); 

     pane.getChildren().add(root); 
     Scene scene = new Scene(pane, 500, 500); 
     stage.setScene(scene); 
     stage.show(); 

     new Thread(() -> { 
      Random r = new Random(); 
      try { 
       while (true) { 
        expand = expand * 1.1; 
        Thread.sleep(700); 
        Platform.runLater(() -> { 
         root.getChildren().add(new Circle(r.nextInt((int)(1000*expand)) - 500*expand, r.nextInt((int)(1000*expand)) - 500*expand, r.nextInt(50)+30)); 
        }); 
       } 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     }).start(); 
    } 

    static double expand = 1.0; 
} 
+1

哇,拉姆達! :) –

回答

1

因爲您在添加每個圓之後更改了組的大小,因此觸發了窗格內組的大小重定位。

您可以:

  1. 直接加入圈子窗格

    pane.getChildren().add(new Circle(... 
    
  2. 添加一個大的背景來解決團隊規模:

    // numbers are huge because you are using 1/5 scaling 
    Rectangle base = new Rectangle(-10000, -10000, 20000, 20000); 
    base.setFill(Color.LIGHTGRAY); 
    root.getChildren().add(base); 
    
+0

謝謝,但這兩種解決方案都不可接受。我總是可以添加一個圈子到30000,所以有同樣的問題。而且我需要能夠整體移動該組,因此我無法將圓圈添加到該窗格。 – mentics

5

首先,我想說你看到的行爲c通過一個更小的程序來實現,更不用說那些你爲圈子做的計算了。 r.nextInt(250)對於圓圈的位置已經足以看到行爲並且更容易看到會發生什麼。另外,對於調試,我添加了一個可見的矩形綁定到該集團layoutBounds中的窗格,在那裏你可以看看會發生什麼:

final Rectangle background = new Rectangle(0, 0, 0, 0); 

    root.layoutBoundsProperty().addListener(new ChangeListener<Bounds>() { 
     @Override 
     public void changed(ObservableValue<? extends Bounds> observable, Bounds oldValue, Bounds newValue) { 
     background.setX(newValue.getMinX()); 
     background.setY(newValue.getMinY()); 
     background.setWidth(newValue.getWidth()); 
     background.setHeight(newValue.getHeight()); 
     } 
    }); 
    background.setFill(null); 
    background.setStroke(Color.RED); 
    pane.getChildren().add(background); 

那麼,是什麼在這裏發生了什麼?

Group的API:

任何變換,施加到一個組的效果,或狀態將被應用到該組的所有兒童。此類轉換和效果不會包含在本組的佈局範圍內,但如果轉換和效果直接針對本集團的子女設置,則這些轉換和效果將包含在本組的佈局範圍內。

看着你的規模,結果打開:

enter image description here

您將看到該組的邊界是什麼比裏面大。這是因爲應用了轉換:組中的孩子被轉換,但是爲了計算組的邊界,不考慮縮放。 因此,該組位於未轉換的圓的邊界的聯合的窗格上,然後應用圓的轉換。

與實驗結果的聲明進行比較時縮放被關閉:

enter image description here

綜上所述,這是由設計,而不是一個怪異的行爲,因爲集團始終是一樣大並根據未轉變的兒童邊界的聯合進行定位。

編輯

如果你想的節點在它們的位置進行縮放和組不動的話,建議直接縮放組的孩子。你的線程的此實現變化,每5個圈圓的比例,但他們留在同一個位置:

new Thread(new Runnable() { 
     private int count = 0; 
     private double scale1 = .5; 
     private double scale2 = .2; 
     private double currentScale = scale1; 
     @Override 
     public void run() { 
     final Random r = new Random(); 
     try { 
      while (true) { 
      expand = expand * 1.1; 
      Thread.sleep(700); 
      Platform.runLater(new Runnable() { 
       @Override 
       public void run() { 
       System.out.println(count); 
       Circle c = new Circle(r.nextInt(250), r.nextInt(250), 30); 
       c.setScaleX(currentScale); 
       c.setScaleY(currentScale); 
       root.getChildren().add(c); 
       count++; 
       if (count > 5){ 
        count = 0; 
        if (currentScale == scale1){ 
        currentScale = scale2; 
        } else { 
        currentScale = scale1; 
        } 
        Iterator<Node> iterator = root.getChildren().iterator(); 
        while (iterator.hasNext()) { 
        Node next = iterator.next(); 
        next.setScaleX(currentScale); 
        next.setScaleY(currentScale); 
        } 
       } 
       } 
      }); 
      } 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     } 
    }).start(); 
+0

很好的解釋爲什麼。現在...如何使它看起來不這樣做。意思是,如何在添加新節點時使現有節點看起來不會移動。應該有一種方式來計算一個逆向變換或者讓它起作用的東西。 – mentics

+0

我並不完全瞭解您的要求,但是,我編輯我的答案以包含使用縮放比例和節點停留在其位置的示例。 – Sebastian

+0

我正在構建一個平移/縮放UI。單獨轉換每個節點是不可行的。 – mentics

3

這裏真正的問題是,集團的支點 - 旋轉和縮放的相對點 - - 取決於集團的佈局範圍。因此,如果佈局界限發生變化,由於添加新的子項(或現有子項更改位置,大小或旋轉),組中所有變換的相對點也會發生變化。

在JavaFX源代碼中,您可以在Node.java文件中找到支點的定義。方法impl_getPivotX()impl_getPivotY()返回中心x分別。 y佈局邊界的座標。

不幸的是,沒有選項可以手動設置樞軸點。但是,因爲每個節點管理的這些都對標準的轉換上賦予額外的轉換列表,你可以很容易地實現所需的行爲:

final Scale scale = new Scale(); 
group.getTransforms().add(scale); 

// change scale 
scale.setX(2); 
+0

@taotree,得到一些反饋會很棒。這是否能解決您的問題? – Matthias

+0

它爲我工作,thx – Chris

0

我有同樣的問題拉絲其中有說出來的一些值的信號的界限。

使用窗格而不是組。你也使用絕對定位,它不會圍着它的邊界移動。 Pane JavaFx 8

-2

使用窗格而不是組 - 這對我有效。

相關問題