如何将鼠标事件委托给JavaFX中的所有底层重叠窗格?

时间:2016-10-13 14:04:34

标签: java javafx mouseevent glasspane

我有一些顶部装饰窗格,我想处理/预处理鼠标事件,但不应该使用它们,即所有重叠的窗格应该像装饰窗格不重叠一样工作。

怎么做?我多次尝试都失败了。

以下是包含3个窗格的代码。绿色的是“装饰”。任务是使其对鼠标事件透明。黄色和蓝色窗格是工人窗格。它们应该像绿色窗格不重叠一样工作。

但绿色窗格应该会收到鼠标事件。

注释行表示我尝试了什么,评论说出了什么错误:

import javafx.application.Application;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

/**
 * Created by dims on 13.10.2016.
 */
public class DelegateEventsToOverlappedNodes extends Application{


   @Override
   public void start(Stage primaryStage) throws Exception {

      StackPane root = new StackPane();
      root.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)));


      AnchorPane yellowPane = new AnchorPane();
      yellowPane.setBackground(new Background(new BackgroundFill(Color.YELLOW, CornerRadii.EMPTY, Insets.EMPTY)));
      yellowPane.setOnMouseClicked(new EventHandler<MouseEvent>() {
         @Override
         public void handle(MouseEvent event) {
            System.out.println("yellowPane clicked");
         }
      });


      root.getChildren().add(yellowPane);


      Pane bluePane = new Pane();
      bluePane.setBackground(new Background(new BackgroundFill(Color.BLUE, CornerRadii.EMPTY, Insets.EMPTY)));
      bluePane.setOnMouseClicked(new EventHandler<MouseEvent>() {
         @Override
         public void handle(MouseEvent event) {
            System.out.println("bluePane clicked");
         }
      });

      AnchorPane.setLeftAnchor(bluePane, 200.);
      AnchorPane.setRightAnchor(bluePane, 200.);
      AnchorPane.setTopAnchor(bluePane, 200.);
      AnchorPane.setBottomAnchor(bluePane, 200.);


      yellowPane.getChildren().add(bluePane);




      AnchorPane greenPane = new AnchorPane();
      greenPane.setBackground(new Background(new BackgroundFill(Color.rgb(0, 255, 0, 0.9), CornerRadii.EMPTY, Insets.EMPTY)));
      greenPane.setOnMouseClicked(new EventHandler<MouseEvent>() {
         @Override
         public void handle(MouseEvent event) {
            System.out.println("greenPane clicked");
         }
      });


      // greenPane.setVisible(false); // green pane invisible at all

      // greenPane.setMouseTransparent(true); // green clicked doesn't occur

      // greenPane.addEventHandler(Event.ANY, event -> yellowPane.fireEvent(event)); // works for yellow pane, but not for blue sub pane



      root.getChildren().add(greenPane);


      Scene scene = new Scene(root, 800, 600);

      primaryStage.setScene(scene);
      primaryStage.setTitle("DelegateEventsToOverlappedNodes");
      primaryStage.show();

   }

   public static void main(String[] args) {
      DelegateEventsToOverlappedNodes.launch(args);
   }
}

1 个答案:

答案 0 :(得分:0)

您可以再次将greenPane鼠标设置为透明,并将事件过滤器添加到root以预处理鼠标事件:

greenPane.setMouseTransparent(true);
root.addEventFilter(MouseEvent.MOUSE_CLICKED, event -> System.out.println(event));

在事件处理的事件捕获阶段过滤接收事件,而在事件冒泡阶段触发处理程序。您也可以使用事件处理程序,但我认为在这种情况下过滤器更具惯用性(阅读更多here)。

您的代码:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class DelegateEventsToOverlappedNodes extends Application {

    public static void main(String[] args) {
        DelegateEventsToOverlappedNodes.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        // Yellow pane.
        AnchorPane yellowPane = new AnchorPane();
        yellowPane.setBackground(new Background(new BackgroundFill(Color.YELLOW, CornerRadii.EMPTY, Insets.EMPTY)));
        yellowPane.setOnMouseClicked(event -> System.out.println("yellowPane clicked"));

        // Blue pane.
        AnchorPane bluePane = new AnchorPane();
        bluePane.setBackground(new Background(new BackgroundFill(Color.BLUE, CornerRadii.EMPTY, Insets.EMPTY)));
        bluePane.setOnMouseClicked(event -> System.out.println("bluePane clicked"));
        AnchorPane.setLeftAnchor(bluePane, 200.0);
        AnchorPane.setRightAnchor(bluePane, 200.0);
        AnchorPane.setTopAnchor(bluePane, 200.0);
        AnchorPane.setBottomAnchor(bluePane, 200.0);

        // Green pane.
        AnchorPane greenPane = new AnchorPane();
        greenPane.setBackground(new Background(new BackgroundFill(Color.rgb(0, 255, 0, 0.9), CornerRadii.EMPTY, Insets.EMPTY)));
        greenPane.setMouseTransparent(true);

        // Root pane.
        StackPane rootPane = new StackPane();
        rootPane.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)));
        rootPane.addEventFilter(MouseEvent.MOUSE_CLICKED, event -> System.out.println(event));

        // Layout and scene.
        yellowPane.getChildren().add(bluePane);
        rootPane.getChildren().addAll(yellowPane, greenPane);

        primaryStage.setScene(new Scene(rootPane, 800.0, 600.0));
        primaryStage.setTitle("DelegateEventsToOverlappedNodes");
        primaryStage.show();
    }

}

如果您创建greenPane仅用于预处理事件,则不再需要它。