JavaFx - Get the coordinates(x,y) of a node or control whose parent is not a Pane

Mr. Leeds

I am trying to emulate a popup container that will show some hints about the proper format of address. The popup will show whenever the addressTextfield gained focus. The popup should appear under the addressTextfield. The problem is, I used combinations of VBox, HBox, and FlowPane for my layout. The default layoutX and layoutY is zero, and it seem they do not change on runtime.

My Popup Control

enter image description here

My AddressField and the hierarchy

enter image description here

What I got so far...

enter image description here

My Popup control stays on top. I tried binding my popup layoutXProperty() to addressTextFields's layoutXProperty()same in layoutYProperty(). I tried adding a MouseEvent.MOUSE_CLICKEDon addressTextField, added a MouseLocationProperty which will be updated on MouseEvent.MouseClicked and binded it to my popup's layoutXProperty(). But still not making it appear under the addressTextField.

My AddNewAccount Class

package com.strongandwhite.pages.dentistadnstaff;

import com.strongandwhite.customcontrols.CustomComboBox;
import com.strongandwhite.customcontrols.CustomDatePicker;
import com.strongandwhite.customcontrols.CustomPasswordField;
import com.strongandwhite.customcontrols.CustomTextField;
import com.strongandwhite.main.MainWindow;
import com.strongandwhite.models.User;
import com.strongandwhite.pages.Page;
import com.strongandwhite.rules.*;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.DateCell;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;

import java.io.IOException;
import java.time.LocalDate;
import java.time.chrono.ChronoLocalDate;
import java.util.ArrayList;

public class AddNewAccount extends Page {
    private ArrayList<String> gender;
    private ArrayList<String> type;
    private ArrayList<String> position;
    public User user;
    private SimpleDoubleProperty mouseX;
    private SimpleDoubleProperty mouseY;

    @FXML private HBox firstNameHBox;
    private CustomTextField firstNameTextField;

    @FXML private HBox middleNameHBox;
    private CustomTextField middleNameTextField;

    @FXML private HBox lastNameHBox;
    private CustomTextField lastNameTextField;

    @FXML private HBox ageHBox;
    private CustomTextField ageTextField;

    @FXML private HBox genderHBox;
    private CustomComboBox<String> genderComboBox;

    @FXML private HBox addressHBox;
    private CustomTextField addressTextField;

    @FXML private HBox contactHBox;
    private CustomTextField contactTextField;

    @FXML private HBox nationalityHBox;
    private CustomTextField nationalityTextField;

    @FXML private HBox religionHBox;
    private CustomTextField religionTextField;

    @FXML private HBox emailAddressHBox;
    private CustomTextField emailAddressTextField;

    @FXML private HBox birthdateHBox;
    private CustomDatePicker birtdateDatePicker;

    @FXML private HBox accountIDHBox;
    private CustomTextField accountIDTextField;

    @FXML private HBox passwordHBox;
    private CustomPasswordField passwordTextField;

    @FXML private HBox confirmPasswordHBox;
    private CustomPasswordField confirmPasswordTextField;

    @FXML private HBox accountTypeHBox;
    private CustomComboBox<String> accountTypeComboBox;

    @FXML private HBox positionHBox;
    private CustomComboBox<String> positionComboBox;

    @FXML private HBox question1HBox;
    private CustomTextField question1TextField;

    @FXML private HBox question2HBox;
    private CustomTextField question2TextField;

    @FXML private HBox question3HBox;
    private CustomTextField question3TextField;

    @FXML private HBox answer1HBox;
    private CustomTextField answer1TextField;

    @FXML private HBox answer2HBox;
    private CustomTextField answer2TextField;

    @FXML private HBox answer3HBox;
    private CustomTextField answer3TextField;

    @FXML private Button clearButton;

    private AnchorPane addressInfo;
    private Pane coverPane;
    private ScrollPane scrollPane;

    public AddNewAccount(User user, MainWindow mainWindow) {
        this.user = user;

        FXMLLoader loader = new FXMLLoader(getClass().getResource("AddNewAccount.fxml"));
        loader.setController(this);
        loader.setRoot(this);
        try {
            loader.load();
        } catch (IOException e) {
            e.printStackTrace();
        }
        loadTitle("AddNewAccountTitle.fxml");

        FXMLLoader loader1 = new FXMLLoader(getClass().getResource("AddressInfo.fxml"));
        try {
            addressInfo = loader1.load();
        } catch (IOException e) {
            e.printStackTrace();
        }

        coverPane = new Pane();

        firstNameTextField = new CustomTextField(firstNameHBox, customControls);
        firstNameTextField.setRule(new NameRule("First Name"));

        middleNameTextField = new CustomTextField(middleNameHBox, customControls);
        middleNameTextField.setRule(new NameRule("Middle Name"));

        lastNameTextField = new CustomTextField(lastNameHBox, customControls);
        lastNameTextField.setRule(new NameRule("Last Name"));

        birtdateDatePicker = new CustomDatePicker(birthdateHBox, customControls);
        birtdateDatePicker.setRule(new DateRule());

        ageTextField = new CustomTextField(ageHBox, customControls);
        ageTextField.setRule(new NumbersOnlyRule());

        genderComboBox = new CustomComboBox<>(genderHBox, customControls);
        genderComboBox.setRule(new WordRule("Gender"));

        addressTextField = new CustomTextField(addressHBox, customControls);
        addressTextField.setRule(new AddressRule());

        contactTextField = new CustomTextField(contactHBox, customControls);
        contactTextField.setRule(new ContactNumberRule());

        nationalityTextField = new CustomTextField(nationalityHBox, customControls);
        nationalityTextField.setRule(new NameRule("Nationality"));

        religionTextField = new CustomTextField(religionHBox, customControls);
        religionTextField.setRule(new NameRule("Religion"));

        emailAddressTextField = new CustomTextField(emailAddressHBox, customControls);
        emailAddressTextField.setRule(new EmailAddressRule());

        accountIDTextField = new CustomTextField(accountIDHBox, customControls);
        accountIDTextField.setRule(new AccountIDRule());

        passwordTextField = new CustomPasswordField(passwordHBox, customControls);
        passwordTextField.setRule(new PasswordRule());

        confirmPasswordTextField = new CustomPasswordField(confirmPasswordHBox, customControls);
        confirmPasswordTextField.setRule(new PasswordRule());

        accountTypeComboBox = new CustomComboBox<>(accountTypeHBox, customControls);
        accountTypeComboBox.setRule(new WordRule("Account Type"));

        positionComboBox = new CustomComboBox<>(positionHBox, customControls);
        positionComboBox.setRule(new WordRule("Position"));

        question1TextField = new CustomTextField(question1HBox, customControls);
        question1TextField.setRule(new WordRule("Question"));

        question2TextField = new CustomTextField(question2HBox, customControls);
        question2TextField.setRule(new WordRule("Question"));

        question3TextField = new CustomTextField(question3HBox, customControls);
        question3TextField.setRule(new WordRule("Question"));

        answer1TextField = new CustomTextField(answer1HBox, customControls);
        answer1TextField.setRule(new WordRule("Answer"));

        answer2TextField = new CustomTextField(answer2HBox, customControls);
        answer2TextField.setRule(new WordRule("Answer"));

        answer3TextField = new CustomTextField(answer3HBox, customControls);
        answer3TextField.setRule(new WordRule("Answer"));

        clearButton.setOnAction(event -> clearPageFields());

        birtdateDatePicker.setDefaultDate(LocalDate.now().minusYears(18));
        birtdateDatePicker.setDayCellFactory(param -> new DateCell() {
            @Override
            public void updateItem(LocalDate item, boolean empty) {
                super.updateItem(item, empty);
                if(item.isBefore(ChronoLocalDate.from(LocalDate.now().minusYears(76).minusMonths(1)))||item.isAfter(ChronoLocalDate.from(LocalDate.now().minusYears(18).plusMonths(1)))) {
                    this.setDisable(true);
                }
            }
        });

        user.ageProperty().bind(birtdateDatePicker.ageProperty());
        ageTextField.textProperty().bind(user.ageProperty().asString());

        gender = new ArrayList<>();
        gender.add("Male");
        gender.add("Female");
        genderComboBox.setItems(gender);

        type = new ArrayList<>();
        type.add("Administrator");
        type.add("Standard");
        type.add("Limited");
        accountTypeComboBox.setItems(type);

        position = new ArrayList<>();
        position.add("Dentist");
        position.add("Receptionist");
        position.add("Staff");
        positionComboBox.setItems(position);

        answer1TextField.editableProperty().bind(question1TextField.textProperty().isNotEmpty());
        answer1TextField.editableProperty().addListener(event-> {
            if(question1TextField.textProperty().getValue().trim().isEmpty()) answer1TextField.clear();
        });

        answer2TextField.editableProperty().bind(question2TextField.textProperty().isNotEmpty());
        answer2TextField.editableProperty().addListener(event-> {
            if(question2TextField.textProperty().getValue().trim().isEmpty()) answer2TextField.clear();
        });

        answer3TextField.editableProperty().bind(question3TextField.textProperty().isNotEmpty());
        answer3TextField.editableProperty().addListener(event-> {
            if(question3TextField.textProperty().getValue().trim().isEmpty()) answer3TextField.clear();
        });

        mainWindow.getActivePagePane().getChildren().add(getPageTitle());

        scrollPane = (ScrollPane) mainWindow.getActivePagePane().getChildren().get(0);
        scrollPane.vvalueProperty().addListener(event-> scrollPane.requestFocus());

        addressInfo.visibleProperty().bind(addressTextField.getTextField().focusedProperty());
        coverPane.setPickOnBounds(false);
        mainWindow.getActivePagePane().getChildren().add(coverPane);
        coverPane.getChildren().add(addressInfo);
        addressInfo.layoutXProperty().bind(addressTextField.getTextField().layoutXProperty());
        addressInfo.layoutYProperty().bind(addressTextField.getTextField().layoutYProperty());
    }
}

My CustomTextField Class

package com.strongandwhite.customcontrols;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;

import java.util.ArrayList;

public class CustomTextField extends CustomControl {
    private TextField textField;
    private Label textLabel;
    private Button clearButton;

    public CustomTextField(HBox control, ArrayList<CustomControl> customControls) {
        setContainer(control);
        textLabel = (Label) ((VBox)control.getChildren().get(0)).getChildren().get(0);
        setErrorLabel((Label) ((VBox)control.getChildren().get(0)).getChildren().get(2));
        textField = (TextField) ((StackPane)((VBox)control.getChildren().get(0)).getChildren().get(1)).getChildren().get(0);
        clearButton = (Button) ((StackPane)((VBox)control.getChildren().get(0)).getChildren().get(1)).getChildren().get(1);
        textLabel.visibleProperty().bind(textField.textProperty().isNotEmpty());
        clearButton.visibleProperty().bind(textField.textProperty().isNotEmpty().and(textField.focusedProperty()).and(textField.editableProperty()));
        clearButton.setOnAction(event -> textField.clear());
        textField.textProperty().addListener((observable, oldValue, newValue) -> executeRule(getRule(), textField.getText()));
        customControls.add(this);
    }

    public StringProperty textProperty() {
        return textField.textProperty();
    }

    public BooleanProperty editableProperty() {
        return textField.editableProperty();
    }

    public String getText() {
        return textField.getText();
    }

    public void setText(String text) {
        textField.setText(text);
    }

    public TextField getTextField() {
        return textField;
    }

    public void setTextField(TextField textField) {
        this.textField = textField;
    }

    @Override
    public void clear() {
        textField.clear();
    }
}

Is there any way I can get the coordinates of addressTextField relative to my Form?

NOTE: My popup is added on a Pane particulary the coverPane which is above my Form and they are all under StackPane.

Gus

These guys suggest you to use something like:

Bounds boundsInScene = addressTextField.localToScene(addressTextField.getBoundsInLocal());

and then use

boundsInScene.getMinX()
boundsInScene.getMinY()
boundsInScene.getMaxX()
boundsInScene.getMaxY()
boundsInScene.getWidth()
boundsInScene.getHeight() 

to get the values of your component relative to the Scene

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Java

Get the parent node of a node (Firebase)

From Dev

Javafx detachable pane system

From Dev

JavaFX: Get Node by row and column

From Dev

JavaFX: FXML: How to make the child to extend its size to fit the parent pane?

From Dev

how to make child auto-resize (child is Pane, parent is VBox) in javafx

From Dev

Resize a pane in javafx by dragging it

From Dev

Console pane in JavaFX

From Dev

How to center a node within a pane javafx

From Dev

Get real position of a node in JavaFX

From Dev

Adding children to JavaFX Control/Parent classes

From Dev

The user control that is opened in custom task pane of outlook plugin, doesn't get disposed when the pane is closed

From Dev

How to refresh pane in javafx

From Dev

WPF: TreeView get parent node

From Dev

Remove a node without knowing the parent (JavaFX)

From Dev

How to get the X and Y location of a javaFX node for displaying a PopupControl?

From Dev

How to center a node within a pane javafx

From Dev

Pane always on top - JavaFX

From Dev

JavaFX adding custom class to parent node

From Dev

Javafx Pane "forgets" layout

From Dev

Vbox Parent, Pane Child overlapping other components javafx

From Dev

Adding children to JavaFX Control/Parent classes

From Dev

Remove a node without knowing the parent (JavaFX)

From Dev

JavaFX custom MasterDetail pane

From Dev

Extending a Pane in JavaFX

From Dev

What is "pane" in JavaFx?

From Dev

JavaFX - Weird Behavior When Adding Node To Parent

From Dev

get parent node with getElementsByClassName

From Dev

How to get the parent control of WindowsFormsHost?

From Dev

Free scroll pane (JavaFX)