This discussion is archived
8 Replies Latest reply: May 21, 2013 9:55 AM by James_D RSS

how to get the size and position AnchorPane

biochemistry43 Newbie
Currently Being Moderated
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 Newbie
    Currently Being Moderated
    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 Newbie
    Currently Being Moderated
    some idea?
    anything

    no?
  • 3. Re: how to get the size and position AnchorPane
    David Grieve Pro
    Currently Being Moderated
    Look at the javadoc for Node, especially the section on bounding rectangles.
  • 4. Re: how to get the size and position AnchorPane
    biochemistry43 Newbie
    Currently Being Moderated
    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 Newbie
    Currently Being Moderated
    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 Guru
    Currently Being Moderated
    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 Newbie
    Currently Being Moderated
    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 Guru
    Currently Being Moderated
    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

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points