Reputation: 2537
We have a requirement to have a "main Node" that when the mouse hovers inside of it another Node ("hover popup Node") appears in the Scene. When the mouse hovers out of the "main Node" then the "hover popup Node" dissapears. Also, the "main Node" has an "inner Node" within that when clicked, another Node ("click popup Node") appears in the Scene and if clicked again the "click popup Node" dissapears.
The problem we have is that, when the mouse hovers inside the "inner Node", the "hover popup Node" dissapears which we do not want. We only want the "hover popup Node" to dissapear when the mouse hovers outside the "main Node". i.e. when the mouse is inside the "inner Node", we still want the "hover popup Node" to be visible.
See sample code:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class MultiPaneMouseTest extends Application {
private Rectangle hoverPopupNode;
private Rectangle clickPopupNode;
@Override
public void init() throws Exception {
super.init();
}
@Override
public void start(Stage primaryStage) {
BorderPane borderPane = new BorderPane();
Rectangle mainNode = new Rectangle(200, 100);
mainNode.setArcWidth(6);
mainNode.setArcHeight(6);
mainNode.setFill(Color.web("0x00ff00"));
mainNode.setOnMouseEntered(e -> {
System.out.println("mouse entered " + e);
hoverPopupNode.setVisible(true);
});
mainNode.setOnMouseExited(e -> {
System.out.println("mouse exited " + e);
hoverPopupNode.setVisible(false);
});
Rectangle innerNode = new Rectangle(50, 25);
innerNode.setArcWidth(6);
innerNode.setArcHeight(6);
innerNode.setFill(Color.web("0xffffff"));
innerNode.setOnMouseClicked(e -> {
System.out.println("mouse clicked " + e);
clickPopupNode.setVisible(!clickPopupNode.isVisible());
});
hoverPopupNode = new Rectangle(100, 100);
hoverPopupNode.setArcWidth(6);
hoverPopupNode.setArcHeight(6);
hoverPopupNode.setFill(Color.web("0x0000ff"));
hoverPopupNode.setVisible(false);
borderPane.setRight(hoverPopupNode);
clickPopupNode = new Rectangle(100, 100);
clickPopupNode.setArcWidth(6);
clickPopupNode.setArcHeight(6);
clickPopupNode.setFill(Color.web("0xff0000"));
clickPopupNode.setVisible(false);
borderPane.setLeft(clickPopupNode);
StackPane stackPane = new StackPane();
stackPane.getChildren().add(mainNode);
stackPane.getChildren().add(innerNode);
borderPane.setCenter(stackPane);
Scene scene = new Scene(borderPane);
primaryStage.setTitle("Sample Test");
primaryStage.setScene(scene);
primaryStage.setX(500.0);
primaryStage.setY(500.0);
primaryStage.setWidth(500.0);
primaryStage.setHeight(500.0);
primaryStage.show();
}
@Override
public void stop() throws Exception {
super.stop();
}
public static void main(String[] args) {
launch(args);
}
}
Upvotes: 1
Views: 327
Reputation: 209330
Make the mainNode
a Pane
(or suitable subclass) and add the innerNode
to it as a child node. If there is a parent-child relationship between mainNode
and childNode
, then the mouse will still be considered to be hovering over mainNode
when it is over innerNode
. You can set the background of a Pane
(or any region) to achieve the same fill and corner radius effects that you have on the Rectangle
.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class MultiPaneMouseTest extends Application {
private Rectangle hoverPopupNode;
private Rectangle clickPopupNode;
@Override
public void init() throws Exception {
super.init();
}
@Override
public void start(Stage primaryStage) {
BorderPane borderPane = new BorderPane();
StackPane mainNode = new StackPane();
mainNode.setMinSize(200, 100);
mainNode.setMaxSize(200, 100);
mainNode.setBackground(new Background(new BackgroundFill(Color.web("0x00ff00"), new CornerRadii(6), Insets.EMPTY)));
// note you can replace these listeners with
// hoverPopupNode.visibleProperty().bind(mainNode.hoverProperty());
// (but obviously after the hoverPopupNode has been instantiated)
mainNode.setOnMouseEntered(e -> {
System.out.println("mouse entered " + e);
hoverPopupNode.setVisible(true);
});
mainNode.setOnMouseExited(e -> {
System.out.println("mouse exited " + e);
hoverPopupNode.setVisible(false);
});
Rectangle innerNode = new Rectangle(50, 25);
innerNode.setArcWidth(6);
innerNode.setArcHeight(6);
innerNode.setFill(Color.web("0xffffff"));
innerNode.setOnMouseClicked(e -> {
System.out.println("mouse clicked " + e);
clickPopupNode.setVisible(!clickPopupNode.isVisible());
});
mainNode.getChildren().add(innerNode);
hoverPopupNode = new Rectangle(100, 100);
hoverPopupNode.setArcWidth(6);
hoverPopupNode.setArcHeight(6);
hoverPopupNode.setFill(Color.web("0x0000ff"));
hoverPopupNode.setVisible(false);
borderPane.setRight(hoverPopupNode);
clickPopupNode = new Rectangle(100, 100);
clickPopupNode.setArcWidth(6);
clickPopupNode.setArcHeight(6);
clickPopupNode.setFill(Color.web("0xff0000"));
clickPopupNode.setVisible(false);
borderPane.setLeft(clickPopupNode);
StackPane stackPane = new StackPane();
stackPane.getChildren().add(mainNode);
borderPane.setCenter(stackPane);
Scene scene = new Scene(borderPane);
primaryStage.setTitle("Sample Test");
primaryStage.setScene(scene);
primaryStage.setX(500.0);
primaryStage.setY(500.0);
primaryStage.setWidth(500.0);
primaryStage.setHeight(500.0);
primaryStage.show();
}
@Override
public void stop() throws Exception {
super.stop();
}
public static void main(String[] args) {
launch(args);
}
}
Upvotes: 1