Javafx 2 如何使JavaFX组在添加子对象时不四处移动?

Javafx 2 如何使JavaFX组在添加子对象时不四处移动?,javafx-2,Javafx 2,如果您观看下面的测试,您将看到所有的圆都在移动,而不仅仅是添加了一个新的圆。并不是每次都这样。我认为只有当新的孩子在现有的界限之外的时候。但是我怎样才能得到它,这样当我添加另一个圆时,无论我把圆放在哪里,它都不会移动组和它的所有子对象 请注意,如果我不设置组的比例,它们不会全部移动。因此,这与设置比例有关 import javafx.application.*; import javafx.beans.value.*; import javafx.collections.*; import ja

如果您观看下面的测试,您将看到所有的圆都在移动,而不仅仅是添加了一个新的圆。并不是每次都这样。我认为只有当新的孩子在现有的界限之外的时候。但是我怎样才能得到它,这样当我添加另一个圆时,无论我把圆放在哪里,它都不会移动组和它的所有子对象

请注意,如果我不设置组的比例,它们不会全部移动。因此,这与设置比例有关

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;
}
导入javafx.application.*;
导入javafx.beans.value.*;
导入javafx.collections.*;
导入javafx.scene.*;
导入javafx.scene.layout.*;
导入javafx.scene.shape.*;
导入javafx.stage.*;
导入java.util.*;
公共类GroupTest扩展了应用程序{
公共静态void main(字符串[]args){
发射(args);
}
公众假期开始(阶段){
窗格=新窗格();
组根=新组();
//注意:删除这两条setScale*行将停止不希望出现的行为
根.setScaleX(.2);
根.setScaleY(.2);
根.setTranslateX(100);
根。setTranslateY(100);
root.layoutXProperty().addListener(新的ChangeListener()){
@凌驾

public void已更改(observeValue,因为在添加每个圆后更改组的大小,从而触发组在窗格内的重新定位

您可以:

  • 将圆直接添加到窗格中

    pane.getChildren().add(new Circle(...
    
  • 添加大背景以固定组大小:

    // 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);
    

  • 首先,我想说的是,你所看到的行为可以通过一个小得多的程序来实现,更不用说你对圆所做的计算了。
    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);
    
    最终矩形背景=新矩形(0,0,0,0);
    root.layoutBoundsProperty().addListener(新的ChangeListener()){
    @凌驾
    
    public void已更改(observeValue此处的真正问题是组的轴心点(旋转和缩放的相对点)取决于组的布局边界。因此,如果布局边界因添加新子级(或现有子级更改位置、大小或旋转)而更改,组上所有变换的相对点也会更改

    在JavaFX源代码中,您可以在Node.java文件中找到轴心点的定义。方法
    impl_getPivotX()
    impl_getPivotY()
    返回布局边界的中心x和y坐标

    遗憾的是,没有手动设置轴心点的选项。但是,由于每个节点都管理一个附加转换列表,这些转换应用于标准转换之上,因此您可以轻松实现所需的行为:

    final Scale scale = new Scale();
    group.getTransforms().add(scale);
    
    // change scale
    scale.setX(2);
    

    我在画一个信号时遇到了同样的问题,这个信号有一些超出界限的值

    使用窗格而不是组。您也使用绝对定位,并且它不会在其边界周围移动。

    使用javafx.scene.layout.Pane而不是javafx.scene.Group.

    谢谢,但这两种解决方案都是不可接受的。我总是会在30000中添加一个圆,所以也会遇到同样的问题。我需要能够将组作为一个整体移动,所以我不能将圆添加到窗格中。非常透彻地解释了为什么。现在…如何让它看起来不这样做。M首先,如何在添加新节点时使现有节点看起来不移动。应该有一种方法来计算反向转换或使其工作。我不完全理解您的要求,但是,我编辑了我的答案,以包含一个使用缩放的示例,并且节点保持在其位置。我正在构建一个平移缩小/缩放UI。单独变换每个节点是不可行的。@taotree,获得一些反馈会很棒。这能解决您的问题吗?这可能是一个稍微不同的问题,但切换到窗格有时可以解决这些问题。这是因为窗格不会从sam中的子级自动推断其大小e.作为一个群体的方式(如其他答案所述)。
    final Scale scale = new Scale();
    group.getTransforms().add(scale);
    
    // change scale
    scale.setX(2);