1 Reply Latest reply on Sep 17, 2013 2:57 PM by Pavel Safrata-Oracle

    What is the recommended way to handle mouse click events for custom nodes that subclass Panes?

    JamesGiller

      Hi,

      I have created a custom node that is a StackPane containing a Label on top of a Polygon.

       

      import javafx.scene.control.Label;
      import javafx.scene.layout.StackPane;
      import javafx.scene.paint.Color;
      import javafx.scene.shape.Polygon;
      
      
      public class CustomHexagon extends StackPane {
      
          private Polygon hexagon;
      
          private Label overlayText;
      
          public CustomHexagon( String text, double... points ) {
              this.hexagon = new Polygon( points );
              this.overlayText = new Label( text );
              overlayText.setStyle( "-fx-font-weight: bold;" );
           
              hexagon.setStroke( Color.GREEN );
              hexagon.setStrokeWidth( 5.0 );
              hexagon.setFill( Color.WHITE );
           
              this.getChildren().addAll( hexagon, overlayText );
      // Lays out the node where it should be according to the points provided for the Polygon.
              this.setLayoutX( points[0] - getLayoutBounds().getMinX() );
              this.setLayoutY( points[1] - getLayoutBounds().getMinY() );
      // Show the border of the StackPane.
              this.setStyle( "-fx-border-color: black; -fx-border-width: 1; -fx-border-style: dashed;");
          }
      
          public String getOverlayText() {
              return overlayText.getText();
          }
      }
      
      
      

       

      I want to display a tesselation of these custom hexagons. Because a CustomHexagon is a StackPane, not a Polygon, MouseClick events can be picked up when the mouse is clicked outside of the stroke of the hexagon but still within the StackPane (which takes up a rectangle larger than the hexagon). The following program demonstrates this.

       

      public class Main extends Application {
        
          @Override
          public void start(Stage primaryStage) {      
              Group root = new Group();
            
              CustomHexagon[] hexagons = {
                  new CustomHexagon( "00", 10.0, 10.0, 30.0, 10.0, 40.0, 27.3205080756, 30.0, 44.6410161512, 10.0, 44.6410161512, 0.0, 27.3205080756 ),
                  new CustomHexagon( "01", 70.0, 10.0, 90.0, 10.0, 100.0, 27.3205080756, 90.0, 44.6410161512, 70.0, 44.6410161512, 60.0, 27.3205080756 ),
                  new CustomHexagon( "02", 130.0, 10.0, 150.0, 10.0, 160.0, 27.3205080756, 150.0, 44.6410161512, 130.0, 44.6410161512, 120.0, 27.3205080756 ),
                  new CustomHexagon( "03", 190.0, 10.0, 210.0, 10.0, 220.0, 27.3205080756, 210.0, 44.6410161512, 190.0, 44.6410161512, 180.0, 27.3205080756 ),
                  new CustomHexagon( "04", 250.0, 10.0, 270.0, 10.0, 280.0, 27.3205080756, 270.0, 44.6410161512, 250.0, 44.6410161512, 240.0, 27.3205080756 ),
                  new CustomHexagon( "10", 40.0, 27.3205080756, 60.0, 27.3205080756, 70.0, 44.6410161512, 60.0, 61.961524226799995, 40.0, 61.961524226799995, 30.0, 44.6410161512 ),
                  new CustomHexagon( "11", 100.0, 27.3205080756, 120.0, 27.3205080756, 130.0, 44.6410161512, 120.0, 61.961524226799995, 100.0, 61.961524226799995, 90.0, 44.6410161512 ),
                  new CustomHexagon( "12", 160.0, 27.3205080756, 180.0, 27.3205080756, 190.0, 44.6410161512, 180.0, 61.961524226799995, 160.0, 61.961524226799995, 150.0, 44.6410161512 ),
                  new CustomHexagon( "13", 220.0, 27.3205080756, 240.0, 27.3205080756, 250.0, 44.6410161512, 240.0, 61.961524226799995, 220.0, 61.961524226799995, 210.0, 44.6410161512 ),
                  new CustomHexagon( "14", 280.0, 27.3205080756, 300.0, 27.3205080756, 310.0, 44.6410161512, 300.0, 61.961524226799995, 280.0, 61.961524226799995, 270.0, 44.6410161512 ),
                  new CustomHexagon( "20", 10.0, 44.6410161512, 30.0, 44.6410161512, 40.0, 61.961524226799995, 30.0, 79.2820323024, 10.0, 79.2820323024, 0.0, 61.961524226799995 ),
                  new CustomHexagon( "21", 70.0, 44.6410161512, 90.0, 44.6410161512, 100.0, 61.961524226799995, 90.0, 79.2820323024, 70.0, 79.2820323024, 60.0, 61.961524226799995 ),
                  new CustomHexagon( "22", 130.0, 44.6410161512, 150.0, 44.6410161512, 160.0, 61.961524226799995, 150.0, 79.2820323024, 130.0, 79.2820323024, 120.0, 61.961524226799995 ),
                  new CustomHexagon( "23", 190.0, 44.6410161512, 210.0, 44.6410161512, 220.0, 61.961524226799995, 210.0, 79.2820323024, 190.0, 79.2820323024, 180.0, 61.961524226799995 ),
                  new CustomHexagon( "24", 250.0, 44.6410161512, 270.0, 44.6410161512, 280.0, 61.961524226799995, 270.0, 79.2820323024, 250.0, 79.2820323024, 240.0, 61.961524226799995 ),
                  new CustomHexagon( "30", 40.0, 61.961524226799995, 60.0, 61.961524226799995, 70.0, 79.2820323024, 60.0, 96.602540378, 40.0, 96.602540378, 30.0, 79.2820323024 ),
                  new CustomHexagon( "31", 100.0, 61.961524226799995, 120.0, 61.961524226799995, 130.0, 79.2820323024, 120.0, 96.602540378, 100.0, 96.602540378, 90.0, 79.2820323024 ),
                  new CustomHexagon( "32", 160.0, 61.961524226799995, 180.0, 61.961524226799995, 190.0, 79.2820323024, 180.0, 96.602540378, 160.0, 96.602540378, 150.0, 79.2820323024 ),
                  new CustomHexagon( "33", 220.0, 61.961524226799995, 240.0, 61.961524226799995, 250.0, 79.2820323024, 240.0, 96.602540378, 220.0, 96.602540378, 210.0, 79.2820323024 ),
                  new CustomHexagon( "34", 280.0, 61.961524226799995, 300.0, 61.961524226799995, 310.0, 79.2820323024, 300.0, 96.602540378, 280.0, 96.602540378, 270.0, 79.2820323024 ),
                  new CustomHexagon( "40", 10.0, 79.2820323024, 30.0, 79.2820323024, 40.0, 96.602540378, 30.0, 113.9230484536, 10.0, 113.9230484536, 0.0, 96.602540378 ),
                  new CustomHexagon( "41", 70.0, 79.2820323024, 90.0, 79.2820323024, 100.0, 96.602540378, 90.0, 113.9230484536, 70.0, 113.9230484536, 60.0, 96.602540378 ),
                  new CustomHexagon( "42", 130.0, 79.2820323024, 150.0, 79.2820323024, 160.0, 96.602540378, 150.0, 113.9230484536, 130.0, 113.9230484536, 120.0, 96.602540378 ),
                  new CustomHexagon( "43", 190.0, 79.2820323024, 210.0, 79.2820323024, 220.0, 96.602540378, 210.0, 113.9230484536, 190.0, 113.9230484536, 180.0, 96.602540378 ),
                  new CustomHexagon( "44", 250.0, 79.2820323024, 270.0, 79.2820323024, 280.0, 96.602540378, 270.0, 113.9230484536, 250.0, 113.9230484536, 240.0, 96.602540378 )
              };
            
              EventHandler<MouseEvent> mouseClickedHandler = new EventHandler<MouseEvent>() {
      
      
                  @Override
                  public void handle(MouseEvent t) {
                      CustomHexagon h = (CustomHexagon) t.getSource();
                      System.out.println( h.getOverlayText() );
                  }
                
              };
            
              for ( CustomHexagon hexagon : hexagons ) {
                  hexagon.setOnMouseClicked( mouseClickedHandler );
              }
      
      
              root.getChildren().addAll( hexagons );
            
              Scene scene = new Scene(root, 400, 400);
            
              primaryStage.setTitle("Example");
              primaryStage.setScene(scene);
              primaryStage.show();
          }
      
      
      
      
          public static void main(String[] args) {
              launch(args);
          }
      }
      
      
      

       

      After running this program, when one clicks within the intersection of two StackPanes (borders shown by dashed lines), the target of the mouse click event will be the StackPane on top as determined by the order in which they were added to their parent. This is a problem because there is only a small "T" shaped area within each hexagon that when clicked will target that hexagon with an event, rather than adjacent nodes. I would appreciate any reccomendations to solve this problem. Thanks, James Giller