0

I have two controls in my JavaFx Application 1. TextField 2. ListView

I want to place ListView just below the TextField using co-ordinates of TextField. Because position of TextField changes.

Details :

I am creating auto suggestion text field for my project which requires to pop up a list when users type something in text field. that text field may exist anywhere in the scene it can be in another list view also. So what I need precisely is how to obtain co-ordinates of text field on screen so that I can place list view just below the text field.

  • Use a `VBox`, or other [layout pane](http://docs.oracle.com/javase/8/javafx/layout-tutorial/builtin_layouts.htm#JFXLY102) that achieves what you need – James_D Sep 19 '17 at 11:30
  • @James_D Thank you for your reply... Please refer to edit (I have added some details of my current scenario). – AshutoshSurya007 Sep 19 '17 at 11:37
  • Depending on your exact use case, this maybe is a duplicate of this: https://stackoverflow.com/q/36861056/3795043 – findusl Sep 19 '17 at 12:22

3 Answers3

0

I see multiple options here:

  • I think you might be better of using a ContextMenu. When you show a ContextMenu you can define a view that it should be shown relative to and a side of the view to show it.

  • Should a ContextMenu not fulfill your demands, the easiest idea that I have is that you replace your TextField with a VBox and input the TextField and the ListView in the VBox. That will make them be together and you can just position the VBox like you would position your TextField.

  • Last if you want to lay it out yourself, the TextField contains Properties like layoutX and layoutY and height and width. Using those you can calculate where to position your ListView (e.g. Y position of ListView would be textField.layoutY + textField.height). To keep this position up to date I see two options:

    • To position the TextField you have probably overwritten the layoutChildrens method of some Parent, so you can probably put this code there.
    • If not, you can also register ChangeListeners on those Properties to get notified when they change and reposition your ListView accordingly.
findusl
  • 1,811
  • 3
  • 23
  • 42
  • `layoutX` and `layoutY` won't give you the screen coordinates of the text field, though. – James_D Sep 19 '17 at 12:26
  • Thanks a lot... I think ChangeListeners would work for me.. :D – AshutoshSurya007 Sep 19 '17 at 12:29
  • @James_D true, but I didn't understand why he needs screen coordinates in the first place so I didn't put a solution with localToScreen converting. – findusl Sep 19 '17 at 12:40
  • 1
    He mentions a popup: `Popup.show(...)` needs screen coordinates. – James_D Sep 19 '17 at 12:41
  • He says he needs to pop up a list. I didn't infer that it means he is using the Popup class. Might be you are right. If he does he will need to take a look at your answer. Or you want me to extend mine to include what you have in yours? – findusl Sep 19 '17 at 12:46
0

To get the location of a text field in the screen coordinates, you can do

Bounds boundsInScreen = textField.localToScreen(textField.getBoundsInLocal());

This returns a Bounds object, from which you can get the various coordinates, e.g.

Popup popup = ... ;
popup.setWidth(boundsInScreen.getWidth());
popup.show(textField, boundsInScreen.getMinX(), boundsInScreen.getMaxY());
James_D
  • 177,111
  • 13
  • 247
  • 290
0

I Created this helper class that does just that.

public class PositionUtils {

    public static void position(Region movable, Region reference, Anchor movableAnchor, Anchor referenceAnchor, float xOffset, float yOffset) {
        double x = reference.localToScene(reference.getBoundsInLocal()).getMaxX();
        double y = reference.localToScene(reference.getBoundsInLocal()).getMaxY();

        Point referencePoint = referenceAnchor.referencePoint;
        Point movablePoint = movableAnchor.movablePoint;

        x -= (0.5 * movable.getWidth()) * movablePoint.x;
        y += (0.5 * movable.getHeight()) * movablePoint.y;

        x += (0.5 * reference.getWidth()) * referencePoint.x;
        y -= (0.5 * reference.getHeight()) * referencePoint.y;

        movable.setLayoutX(x + xOffset);
        movable.setLayoutY(y + yOffset);
    }

    public static void position(Pane movable, Pane reference, Anchor movableAnchor, Anchor referenceAnchor) {
        position(movable, reference, movableAnchor, referenceAnchor, 0, 0);
    }

    public static void position(Pane movable, Pane reference, Side side) {
        position(movable, reference, side, 0, 0);
    }

    public static void position(Pane movable, Pane reference, Side side, float xOffset, float yOffset) {
        Anchor movableAnchor = null;
        Anchor referenceAnchor = null;
        switch (side) {
            case TOP:
                movableAnchor = Anchor.BOTTOM_CENTER;
                referenceAnchor = Anchor.TOP_CENTER;
                break;
            case BOTTOM:
                movableAnchor = Anchor.TOP_CENTER;
                referenceAnchor = Anchor.BOTTOM_CENTER;
                break;
            case RIGHT:
                movableAnchor = Anchor.CENTER_LEFT;
                referenceAnchor = Anchor.CENTER_RIGHT;
                break;
            case LEFT:
                movableAnchor = Anchor.CENTER_RIGHT;
                referenceAnchor = Anchor.CENTER_LEFT;
                break;
        }
        position(movable, reference, movableAnchor, referenceAnchor, xOffset, yOffset);
    }

    public enum Anchor {
        TOP_LEFT(new Point(0, 0), new Point(-2, 2)),
        TOP_CENTER(new Point(1, 0), new Point(-1, 2)),
        TOP_RIGHT(new Point(2, 0), new Point(0, 2)),
        CENTER_LEFT(new Point(0, -1), new Point(-2, 1)),
        CENTER(new Point(1, -1), new Point(-1, 1)),
        CENTER_RIGHT(new Point(1, -2), new Point(0, 1)),
        BOTTOM_LEFT(new Point(0, -2), new Point(-2, 0)),
        BOTTOM_CENTER(new Point(1, -2), new Point(-1, 0)),
        BOTTOM_RIGHT(new Point(2, -2), new Point(0, 0));

        public Point referencePoint;
        public Point movablePoint;

        Anchor(Point movablePoint, Point referencePoint) {
            this.referencePoint = referencePoint;
            this.movablePoint = movablePoint;
        }
    }

    public enum Side {
        TOP,
        BOTTOM,
        RIGHT,
        LEFT
    }
}
Rafat Rifaie
  • 136
  • 2
  • 14