How to tell if the cursor is over a given component in javaFX

1

I have a component in javaFX and would like to know if the cursor is positioned on it. Is there a function for this?

I tried to create a boolean that stores this using the setOnMouseEntered and setOnMouseExited events, however I use this for two components and the threads of java events ended up creating bugs event ended before the other).

So I would like to know if you have any method to know if the cursor is over a component when the method is called.

Code:

public class BarraLogoffControlador implements Initializable {

    @FXML
    private HBox menu;

    @FXML
    private Button botao_expandir;

    private final HBox painel = new HBox();
    private boolean esta_no_botao = false;
    private boolean esta_no_painel = false;

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        Polygon seta = new Polygon(
                54.0, 52.0,
                54.0, 58.0,
                50.0, 55.0
        );

        this.menu.getStylesheets().add("/iftorrent/gui/barraLogoff/BarraLogoffCSS.css");
        this.menu.setAlignment(Pos.CENTER_RIGHT);
        this.menu.setMinSize(0, 0);
        this.menu.setPrefHeight(ALTURA_BARRA_LOGOFF1);

        this.botao_expandir.setOnMouseEntered((Event event) -> {
            if(!menu.getChildren().contains(painel)){
                menu.getChildren().add(painel);
            }
            esta_no_botao = true;
        });

        this.painel.setOnMouseEntered((Event event) -> {
            esta_no_painel = true;
        });

        this.botao_expandir.setOnMouseExited((Event event) -> {
            esta_no_botao = false;
        });

        this.painel.setOnMouseExited((Event event) -> {
            esta_no_painel = false;
        });

        this.botao_expandir.setGraphic(seta);
        this.botao_expandir.setMinWidth(5);
        this.botao_expandir.setPrefWidth(8);
        this.botao_expandir.setMaxHeight(ALTURA_BARRA_LOGOFF1);
        this.painel.getChildren().addAll(
                new Button("desligar"),
                new Button("fechar"),
                new Button("bloquear")
        );
        this.painel.setId("painel");
        this.painel.setMaxHeight(ALTURA_BARRA_LOGOFF1);
        this.painel.setAlignment(Pos.CENTER);
    }
}

Basically, the idea is a component with a button in which, when positioning the cursor, expands a series of buttons.

The code in FXML only creates an HBox called menu and adds the Button button_expandir in.

The problem is: the component consists of two parts, a button and an hbox. When we move the mouse from one component to another, it exits from one component and enters another, thus calling two events. In the input event, it updates a boolean variable that stores if the cursor is over the component, already in the output event, it checks if the cursor is over any of the components and, if not, it hides the hbox. The problem is that the output event is occurring before the input event, so the cursor check is done before the boolean is updated.

    
asked by anonymous 15.09.2017 / 20:37

1 answer

1

I believe this is the result you want, so I understand:

@FXML
private Button btn;

// ...

@FXML
public void mostrarPopup(){
    Popup popup = new Popup();
    popup.setAutoHide(true);

    HBox hb = new HBox();
    Button btn2 = new Button("Botão 2");
    Button btn3 = new Button("Botão 3");
    hb.getChildren().addAll(btn2, btn3);

    popup.getContent().addAll(hb);
    Bounds bounds = btn.localToScreen(btn.getBoundsInLocal());
    // X + Width = Lado direito
    popup.show(btn, bounds.getMinX() + bounds.getWidth(), bounds.getMinY());

    // Fecha o popup quando o mouse sai do HBox
    hb.setOnMouseExited((MouseEvent t) -> {
        popup.hide();
    });
}

Just add the showPopup () method to your button's onMouseEntered:

<Button fx:id="btn" layoutX="129.0" layoutY="26.0" mnemonicParsing="false" onMouseEntered="#mostrarPopup" text="Button" />

The result is as follows:

    
18.09.2017 / 21:14