Events JavaFx按钮事件冒泡

Events JavaFx按钮事件冒泡,events,button,javafx,pane,Events,Button,Javafx,Pane,我正在从事一个在java8中使用javafx的项目。 我关注了一个奇怪的情况: 一个面板(属于javafx.scene.layout.Pane类),包含一个按钮(javafx.scene.control.button)和另一个窗格。我希望一个鼠标点击事件会被弹出到父级。但这只是我单击窗格时的情况,而不是单击按钮时的情况。下面是一个具有此行为的非常简单示例的代码。有人有解决这个问题的建议吗?我知道我可以基于窗格创建自己的按钮。。但这只是一个令人讨厌的解决办法。 干杯 包应用; 导入javafx.a

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

包应用;
导入javafx.animation.TranslateTransition;
导入javafx.application.application;
导入javafx.event.event;
导入javafx.event.EventHandler;
导入javafx.stage.stage;
导入javafx.scene.scene;
导入javafx.scene.control.Button;
导入javafx.scene.image.image;
导入javafx.scene.image.ImageView;
导入javafx.scene.layout.BorderPane;
导入javafx.scene.layout.Pane;
导入javafx.util.Duration;
公共类主扩展应用程序{
双刻度;
@凌驾
公共无效开始(阶段primaryStage){
试一试{
BorderPane根=新的BorderPane();
场景=新场景(根,400400);
scene.getStylesheets().add(getClass().getResource(“application.css”).toExternalForm());
按钮btn=新按钮(“测试”);
btn.设置布局X(50);
窗格p2=新窗格();
p2.setPrefSize(20,20);
p2.设置样式(“-fx背景色:#440000”);
窗格p=新窗格();
p、 getChildren().add(btn);
p、 getChildren().add(p2);
根.立顶(p);
p、 setOnMouseClicked(新事件处理程序(){
@凌驾
公共无效句柄(事件){
System.out.println(“事件源”+event.getSource()+“目标”+event.getTarget());
}
});
初级阶段。场景(场景);
primaryStage.show();
}捕获(例外e){
e、 printStackTrace();
}
}
公共静态void main(字符串[]args){
发射(args);
}
}

默认情况下,按钮将使用鼠标单击事件,而窗格将不会

如果要使用父窗格事件处理程序截获按钮鼠标单击,则应使用来截获(在捕获阶段而不是冒泡阶段截获事件)


如果您需要了解捕获与冒泡的概念,请仔细阅读。

多亏了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);
            }  
        }
    }
包应用;
导入com.oracle.jrockit.jfr.EventToken;
导入javafx.application.application;
导入javafx.event.event;
导入javafx.event.EventHandler;
导入javafx.event.EventTarget;
导入javafx.event.EventType;
导入javafx.scene.Node;
导入javafx.scene.scene;
导入javafx.scene.control.Button;
导入javafx.scene.input.MouseEvent;
导入javafx.scene.layout.BorderPane;
导入javafx.scene.layout.Pane;
导入javafx.stage.stage;
公共类主扩展应用程序{
双刻度;
@凌驾
公共无效开始(阶段primaryStage){
试一试{
BorderPane根=新的BorderPane();
场景=新场景(根,400400);
scene.getStylesheets().add(getClass().getResource(“application.css”).toExternalForm());
按钮btn=新按钮(“测试”);
btn.设置布局X(50);
窗格p2=新窗格();
p2.setPrefSize(20,20);
p2.设置样式(“-fx背景色:#440000”);
窗格p=新窗格();
p、 getChildren().add(btn);
p、 getChildren().add(p2);
窗格p3=新窗格();
p3.getChildren().add(p);
根。setTop(p3);
p3.setOnMouseClicked(新的EventHandler(){
@凌驾
公共无效句柄(事件){
System.out.println(“顶部窗格获得点击事件”);
}
});
//定义一个事件过滤器
EventHandler筛选器=新的EventHandler(){
@凌驾
公共无效句柄(事件){
System.out.println(“过滤出事件”+event.getEventType()+“源”+event.getSource()+“目标”+event.getTarget());
Node Node=(Node)event.getTarget();
试一试{
按钮b=(按钮)事件.getSource();
firevent(新的MyEvent(b.getText());
}捕获(例外e){
node.firevent(新的MyEvent(“窗格”);
}
event.consume();
}
};
btn.addEventFilter(鼠标点击MouseEvent.MOUSE_,过滤);
p2.addEventFilter(鼠标点击MouseEvent.MOUSE_,过滤);
p、 addEventHandler(按下MyEvent.BUTTON_,新建MyEventHandler());
初级阶段。场景(场景);
primaryStage.show();
}捕获(例外e){
e、 printStackTrace();
}
}
公共静态void main(字符串[]args){
发射(args);
}
//处理者
类MyEventHandler实现EventHandler{
@凌驾
公共无效句柄(MyEvent事件){
System.out.println(“MyEvent”+事件数据);
}
}
//事件
静态类MyEvent扩展事件{
公共最终静态事件类型按钮
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);
            }  
        }
    }