我正在使用java8中的javafx开发一个项目。 我关注一个奇怪的情况: 包含按钮(javafx.scene.control.Button)和另一个窗格的面板(类javafx.scene.layout.Pane)。我希望鼠标点击的事件可以冒泡到父级。但是,只有当我点击窗格时才会出现这种情况,而单击按钮时则不会发生这种情况。下面是具有此行为的一个非常简单的示例的代码。有没有人有解决这个问题的建议?我知道我可以根据窗格创建自己的按钮..但这只是一个讨厌的解决方法。 干杯
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);
}
}
答案 0 :(得分:8)
默认情况下,该按钮将使用鼠标单击事件,而窗格则不会。
如果要使用父窗格事件处理程序拦截鼠标单击按钮,则应使用event filter这样做(在捕获阶段而不是冒泡阶段拦截事件)。
如果您需要了解捕获与冒泡概念,请阅读event processing。
答案 1 :(得分: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);
}
}
}