3

我正在使用 java8 中的 javafx 开发一个项目。我关注了一个奇怪的情况:一个面板(类 javafx.scene.layout.Pane)包含一个按钮(javafx.scene.control.Button)和另一个窗格。我希望鼠标单击事件会冒泡到父级。但这仅在我单击窗格时出现,并且在我单击按钮时不会发生。以下是具有此行为的一个非常简单的示例的代码。有没有人有解决这个问题的建议?我知道我可以基于窗格创建自己的按钮.. 但这只是一个讨厌的解决方法。干杯

    package application;

    import javafx.animation.TranslateTransition;
    import javafx.application.Application;
    import javafx.event.Event;
    import javafx.event.EventHandler;
    import javafx.stage.Stage;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.image.Image;
    import javafx.scene.image.ImageView;
    import javafx.scene.layout.BorderPane;
    import javafx.scene.layout.Pane;
    import javafx.util.Duration;


    public class Main extends Application {

        double curScale;


        @Override
        public void start(Stage primaryStage) {
            try {
                BorderPane root = new BorderPane();
                Scene scene = new Scene(root,400,400);
                scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());


                Button btn = new Button("test");
                btn.setLayoutX(50);
                Pane p2 = new Pane();
                p2.setPrefSize(20,20);
                p2.setStyle("-fx-background-color: #440000");
                Pane p = new Pane();
                p.getChildren().add(btn);
                p.getChildren().add(p2);

                root.setTop(p);

                p.setOnMouseClicked(new EventHandler<Event>() {

                    @Override
                    public void handle(Event event) {
                        System.out.println("event source " + event.getSource() + " target : " + event.getTarget());

                    }
                });

                primaryStage.setScene(scene);
                primaryStage.show();
            } catch(Exception e) {
                e.printStackTrace();
            }
        }

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

2 回答 2

9

默认情况下,按钮会消耗鼠标点击事件,而窗格不会。

如果要使用父窗格事件处理程序拦截按钮鼠标单击,则应使用事件过滤器来执行此操作(在捕获阶段而不是冒泡阶段拦截事件)。

如果您需要了解捕获与冒泡的概念,请阅读事件处理。

于 2014-05-21T08:57:08.327 回答
1

感谢jewelsea的回答,我想出了这个工作示例:

package application;



import com.oracle.jrockit.jfr.EventToken;

import javafx.application.Application;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.event.EventTarget;
import javafx.event.EventType;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;


    public class Main extends Application {

        double curScale;


        @Override
        public void start(Stage primaryStage) {
            try {
                BorderPane root = new BorderPane();
                Scene scene = new Scene(root,400,400);
                scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());


                Button btn = new Button("test");
                btn.setLayoutX(50);
                Pane p2 = new Pane();
                p2.setPrefSize(20,20);
                p2.setStyle("-fx-background-color: #440000");
                Pane p = new Pane();
                p.getChildren().add(btn);
                p.getChildren().add(p2);

                Pane p3 = new Pane();
                p3.getChildren().add(p);
                root.setTop(p3);

                p3.setOnMouseClicked(new EventHandler<Event>() {

                    @Override
                    public void handle(Event event) {
                        System.out.println("top pane got the clicked event");
                    }
                });


                // Define an event filter
                EventHandler filter = new EventHandler<Event>() {

                    @Override
                    public void handle(Event event) {
                        System.out.println("Filtering out event " + event.getEventType() +  "   source  " + event.getSource() + "   target " + event.getTarget());
                        Node node = (Node) event.getTarget();
                        try{
                            Button b = (Button)event.getSource();
                            node.fireEvent(new MyEvent( b.getText() ));
                        }catch(Exception e){
                            node.fireEvent(new MyEvent( "pane" ));
                        }

                event.consume();
                    }
                };

                btn.addEventFilter(MouseEvent.MOUSE_CLICKED, filter);
                p2.addEventFilter(MouseEvent.MOUSE_CLICKED, filter);

                p.addEventHandler(MyEvent.BUTTON_PRESSED, new MyEventHandler());

                primaryStage.setScene(scene);
                primaryStage.show();
            } catch(Exception e) {
                e.printStackTrace();
            }
        }

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



    // The Handler
    class MyEventHandler implements EventHandler<MyEvent> {

        @Override
        public void handle(MyEvent event) {

            System.out.println("MyEvent " + event.data);

        }
    }

    // The Event
        static class MyEvent extends Event {

            public final static EventType<MyEvent> BUTTON_PRESSED = new EventType(ANY, "BUTTON_PRESSED");

            public String data;

            public MyEvent() {
                this(BUTTON_PRESSED);
            }

            public MyEvent(String what){
                    this(BUTTON_PRESSED);
                    data = what;
            }

            public MyEvent(EventType<? extends Event> arg0) {
                super(arg0);
            }
            public MyEvent(Object arg0, EventTarget arg1, EventType<? extends Event> arg2) {
                super(arg0, arg1, arg2);
            }  
        }
    }
于 2014-05-21T12:00:40.613 回答