8 Replies Latest reply: May 21, 2013 11:55 AM by James_D RSS

    how to get the size and position AnchorPane

    biochemistry43
      They could give me a clue how to get the size and position (x, y) of a AnchorPane within a Split-Pane

      I thought it would be something simple and I tried several methods that seemed logical but to no value.

      I hope you can guide me a bit on how to do

      Thanks in advance.
        • 1. Re: how to get the size and position AnchorPane
          biochemistry43
          Someone know how to do this?
          or perhaps similar alternative.

          Thanks for your help
          • 2. Re: how to get the size and position AnchorPane
            biochemistry43
            some idea?
            anything

            no?
            • 3. Re: how to get the size and position AnchorPane
              David Grieve
              Look at the javadoc for Node, especially the section on bounding rectangles.
              • 4. Re: how to get the size and position AnchorPane
                biochemistry43
                Actually I've tried that way but I get no results

                anchorPane.getBoundsInLocal (). getHeight ()

                returns 0.0
                • 5. Re: how to get the size and position AnchorPane
                  biochemistry43
                  someone would help me?

                  And really made some attempts and did not return any results, always returns 0.0 and ignored me why
                  • 6. Re: how to get the size and position AnchorPane
                    James_D
                    If I understand, you want the size and location of an AnchorPane relative to the bounds of the SplitPane in which you've placed it.

                    In general, to get the bounds of a node relative to its parent, you use getBoundsInParent(). However, it seems that when you place a Node in a SplitPane, it is wrapped internally by the split pane in some other container. So you need to recursively call getParent() until you reach the SplitPane itself, adding the coordinates as you go.

                    This example has a SplitPane with two AnchorPanes in it. I create observable object properties containing the bounds of each anchor pane relative to the split pane, as described above. I listen to each and output the new bounds when they change, and also for the second pane use the bounds to overlay a semi-transparent rectangle on top of the pane. (Obviously, there are way easier ways to achieve this effect, but it provides a nice test that I'm calculating the bounds correctly.)

                    In theory, I should really listen for changes in the boundsInParent properties of all the Nodes from the content itself up to the SplitPane; but I can't see any way the bounds of the content relative to the split pane would change without the size of the content changing, so I think just listening to the boundsInParent property of the content itself suffices.
                    import javafx.application.Application;
                    import javafx.beans.binding.ObjectBinding;
                    import javafx.beans.property.ObjectProperty;
                    import javafx.beans.property.SimpleObjectProperty;
                    import javafx.beans.value.ChangeListener;
                    import javafx.beans.value.ObservableValue;
                    import javafx.event.ActionEvent;
                    import javafx.event.EventHandler;
                    import javafx.geometry.BoundingBox;
                    import javafx.geometry.Bounds;
                    import javafx.geometry.Orientation;
                    import javafx.scene.Node;
                    import javafx.scene.Parent;
                    import javafx.scene.Scene;
                    import javafx.scene.SceneBuilder;
                    import javafx.scene.control.ButtonBuilder;
                    import javafx.scene.control.SplitPane;
                    import javafx.scene.control.SplitPaneBuilder;
                    import javafx.scene.layout.AnchorPane;
                    import javafx.scene.paint.Color;
                    import javafx.scene.shape.Rectangle;
                    import javafx.stage.Stage;
                    
                    public class SplitPaneTest extends Application {
                    
                      @Override
                      public void start(Stage primaryStage) {
                        final AnchorPane pane1 = new AnchorPane();
                        final AnchorPane pane2 = new AnchorPane();
                    
                        final SplitPane splitPane = SplitPaneBuilder.create()
                            .orientation(Orientation.HORIZONTAL).items(pane1, pane2)
                            .dividerPositions(new double[] { .3 }).build();
                    
                        pane2.getChildren().add(
                            ButtonBuilder.create().text("Reset Divider")
                                .onAction(new EventHandler<ActionEvent>() {
                                  @Override
                                  public void handle(ActionEvent event) {
                                    splitPane.setDividerPositions(.3);
                                  }
                                }).build());
                    
                        final AnchorPane root = new AnchorPane();
                    
                        // force the split pane to fill the root:
                        AnchorPane.setTopAnchor(splitPane, 0d);
                        AnchorPane.setLeftAnchor(splitPane, 0d);
                        AnchorPane.setBottomAnchor(splitPane, 0d);
                        AnchorPane.setRightAnchor(splitPane, 0d);
                        root.getChildren().add(splitPane);
                    
                        ObjectProperty<Bounds> pane1Bounds = createBoundsRelToSplitPaneProperty(pane1, splitPane);
                        pane1Bounds.addListener(new ChangeListener<Bounds>() {
                          @Override
                          public void changed(ObservableValue<? extends Bounds> obs,
                              Bounds oldBounds, Bounds newBounds) {
                            System.out.println("Pane 1: " + newBounds);
                          }
                        });
                    
                        final Rectangle pane2Overlay = new Rectangle();
                        pane2Overlay.setFill(Color.ANTIQUEWHITE.deriveColor(0, 1, 1, 0.5));
                        pane2Overlay.setMouseTransparent(true);
                        root.getChildren().add(pane2Overlay);
                    
                        ObjectProperty<Bounds> pane2Bounds = createBoundsRelToSplitPaneProperty(pane2, splitPane);
                        pane2Bounds.addListener(new ChangeListener<Bounds>() {
                          @Override
                          public void changed(ObservableValue<? extends Bounds> obs, Bounds oldBounds, Bounds newBounds) {
                            System.out.println("Pane 2: " + newBounds);
                            pane2Overlay.setX(newBounds.getMinX());
                            pane2Overlay.setY(newBounds.getMinY());
                            pane2Overlay.setWidth(newBounds.getWidth());
                            pane2Overlay.setHeight(newBounds.getHeight());
                          }
                        });
                    
                        Scene primaryScene = SceneBuilder.create().root(root).width(500).height(500).build();
                    
                        primaryStage.setScene(primaryScene);
                        primaryStage.setTitle("Name");
                        primaryStage.show();
                      }
                    
                      public static void main(String[] args) {
                        launch(args);
                      }
                    
                      private ObjectProperty<Bounds> createBoundsRelToSplitPaneProperty(
                          final Node content, final SplitPane splitPane) {
                        ObjectProperty<Bounds> bounds = new SimpleObjectProperty<Bounds>();
                        bounds.bind(new ObjectBinding<Bounds>() {
                          {
                            super.bind(content.boundsInParentProperty());
                          }
                    
                          @Override
                          protected Bounds computeValue() {
                            final Bounds boundsInParent = content.getBoundsInParent();
                            double w = boundsInParent.getWidth();
                            double h = boundsInParent.getHeight();
                            double x = boundsInParent.getMinX();
                            double y = boundsInParent.getMinY();
                            for (Parent p = content.getParent(); p != null && p != splitPane; p = p.getParent()) {
                              Bounds b = p.getBoundsInParent();
                              x += b.getMinX();
                              y += b.getMinY();
                            }
                            return new BoundingBox(x, y, w, h);
                          }
                        });
                        return bounds;
                      }
                    }
                    • 7. Re: how to get the size and position AnchorPane
                      biochemistry43
                      First of all, thanks again for your help.

                      Although still did not review fully what provide me, I suspect that's not exactly what I want. I regret not being specific on that. What I need is your position on the screen.

                      It happens that I need to send those positions through socket to another application, which will be adjusted to the screen, depending on the location of the gui.
                      • 8. Re: how to get the size and position AnchorPane
                        James_D
                        You can use the same basic idea; just keep on iterating up from parent node to parent node until you run out of parents (i.e. you get to the root). Then get the location of the scene in the window, and the location of the window. Something like:
                        public Bounds getBoundsOnScreen(Node n) {
                          Scene scene = n.getScene();
                          if (scene == null) {
                            return null ;
                          }
                          Window window = scene.getWindow();
                          if (window == null) {
                            return null ;
                          }
                          Bounds b = n.getBoundsInParent();
                          double w = b.getWidth();
                          double h = b.getHeight();
                          double x = b.getMinX();
                          double y = b.getMinY();
                          for (Parent p = n.getParent(); p!=null; p=p.getParent()) {
                            b = p.getBoundsInParent();
                            x += b.getMinX();
                            y += b.getMinY();
                          }
                          x = x + scene.getX() + window.getX(); 
                          y = y + scene.getY() + window.getY();
                          return new BoundingBox(x, y, w, h);
                        }
                        (This is completely untested, but I think it should work, unless there are typos.)

                        Edited by: James_D on May 21, 2013 9:54 AM