在 JavaFX 中,我们可以开发 GUI 应用程序、Web 应用程序和图形应用程序。在此类应用程序中,每当用户与应用程序 (节点) 交互时,都会称其发生了事件。
例如,单击按钮、移动鼠标、通过键盘输入字符、从列表中选择项目、滚动页面是导致事件发生的活动。
事件类型
JavaFX 中的事件
JavaFX 支持处理各种事件。程序包 javafx.event 的名为 Event 的类是事件的基类。
其任何 subclass 的实例都是一个 event。JavaFX 提供了各种各样的事件。
事件处理
事件处理是控制事件并决定在事件发生时应该发生什么的机制。此机制具有称为事件处理程序的代码,该代码在事件发生时执行。
JavaFX 提供处理程序和过滤器来处理事件。在 JavaFX 中,每个事件都有
JavaFX 中事件处理的阶段
每当生成事件时,JavaFX 都会经历以下阶段。
路线建设
每当生成事件时,事件的默认/初始路由都由构造 Event Dispatch chain 确定。它是从阶段到源节点的路径。
下面是上述场景中我们点击 play 按钮时生成的事件的 event dispatch 链。
事件捕获阶段
在构建事件调度链之后,应用程序的根节点调度事件。此事件会传播到 dispatch 链中的所有节点(从上到下)。如果这些节点中的任何一个为生成的事件注册了过滤器,则将执行该过滤器。如果调度链中没有一个节点具有所生成事件的过滤器,则将其传递给目标节点,最后由目标节点处理该事件。
事件冒泡阶段
在事件冒泡阶段,事件从目标节点传输到阶段节点(从下到上)。如果事件调度链中的任何节点为生成的事件注册了处理程序,则将执行该事件。如果这些节点都没有处理事件的处理程序,则事件将到达根节点,最后进程将完成。
事件处理程序和筛选器
事件过滤器和处理程序是包含用于处理事件的应用程序逻辑的过滤器和处理程序。一个节点可以注册到多个处理程序/过滤器。对于父子节点,您可以为父节点提供一个通用的过滤器/处理程序,该过滤器/处理程序将作为所有子节点的默认值处理。
如上所述,在事件期间,processing 是执行的过滤器,在事件冒泡阶段,将执行处理程序。所有处理程序和过滤器都实现包 javafx.event 的接口 EventHandler 。
JavaFX - 使用便捷方法
事件处理程序被简单地定义为在事件发生后要发生的作。可以注册这些事件处理程序以处理更复杂的事件;并且您可以使用便捷的方法在 JavaFX 应用程序中注册事件处理程序。可以创建和注册事件处理程序,以响应鼠标事件、键盘事件、窗口事件等事件。
某些 JavaFX 类定义事件处理程序属性,这些属性提供了一种注册事件处理程序的方法。将事件处理程序属性设置为用户定义的事件处理程序会自动注册处理程序以接收相应的事件类型。事件处理程序属性的 setter 方法是用于注册事件处理程序的便捷方法。
使用便捷方法进行事件处理
JavaFX 中的某些类定义事件处理程序属性。通过使用这些属性各自的 setter 方法将值设置为这些属性,您可以注册到事件处理程序。这些方法称为便捷方法。
这些方法中的大多数都存在于 Node、Scene、Window 等类中,并且它们可用于它们的所有子类。
语法
以下是用于注册事件处理程序的 Convenience 方法的格式:
java">setOnEvent-type(EventHandler<? super event-class> value)
例如,要向按钮添加鼠标事件侦听器,可以使用便捷方法 setOnMouseClicked(),如下所示。
java">playButton.setOnMouseClicked((new EventHandler<MouseEvent>() { public void handle(MouseEvent event) { System.out.println("Hello World"); pathTransition.play(); }
}));
例
以下程序是一个示例,它演示了使用 Convenience 方法在 JavaFX 中进行事件处理。
将此代码保存在名为 ConvenienceMethodsExample.java 的文件中。
java">import javafx.animation.PathTransition;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.event.EventHandler; import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color; import javafx.scene.shape.Circle;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.stage.Stage;
import javafx.util.Duration; public class ConvenienceMethodsExample extends Application { @Override public void start(Stage stage) { //Drawing a Circle Circle circle = new Circle(); //Setting the position of the circle circle.setCenterX(300.0f); circle.setCenterY(135.0f); //Setting the radius of the circle circle.setRadius(25.0f); //Setting the color of the circle circle.setFill(Color.BROWN); //Setting the stroke width of the circle circle.setStrokeWidth(20); //Creating a Path Path path = new Path(); //Moving to the staring point MoveTo moveTo = new MoveTo(208, 71); //Creating 1st line LineTo line1 = new LineTo(421, 161); //Creating 2nd line LineTo line2 = new LineTo(226,232); //Creating 3rd line LineTo line3 = new LineTo(332,52); //Creating 4th line LineTo line4 = new LineTo(369, 250); //Creating 5th line LineTo line5 = new LineTo(208, 71); //Adding all the elements to the path path.getElements().add(moveTo); path.getElements().addAll(line1, line2, line3, line4, line5); //Creating the path transition PathTransition pathTransition = new PathTransition(); //Setting the duration of the transition pathTransition.setDuration(Duration.millis(1000)); //Setting the node for the transition pathTransition.setNode(circle); //Setting the path for the transition pathTransition.setPath(path); //Setting the orientation of the path pathTransition.setOrientation(PathTransition.OrientationType.ORTHOGONAL_TO_TAN GENT);//Setting the cycle count for the transition pathTransition.setCycleCount(50); //Setting auto reverse value to true pathTransition.setAutoReverse(false);//Creating play button Button playButton = new Button("Play"); playButton.setLayoutX(300); playButton.setLayoutY(250); circle.setOnMouseClicked (new EventHandler<javafx.scene.input.MouseEvent>() { @Override public void handle(javafx.scene.input.MouseEvent e) { System.out.println("Hello World"); circle.setFill(Color.DARKSLATEBLUE); } }); playButton.setOnMouseClicked((new EventHandler<MouseEvent>() { public void handle(MouseEvent event) { System.out.println("Hello World"); pathTransition.play(); } })); //Creating stop button Button stopButton = new Button("stop"); stopButton.setLayoutX(250); stopButton.setLayoutY(250); stopButton.setOnMouseClicked((new EventHandler<MouseEvent>() { public void handle(MouseEvent event) { System.out.println("Hello World"); pathTransition.stop(); } }));//Creating a Group object Group root = new Group(circle, playButton, stopButton); //Creating a scene object Scene scene = new Scene(root, 600, 300); scene.setFill(Color.LAVENDER); //Setting title to the Stage stage.setTitle("Convenience Methods Example"); //Adding scene to the stage stage.setScene(scene); //Displaying the contents of the stage stage.show(); } public static void main(String args[]){ launch(args); }
}
JavaFX - 事件过滤器
事件筛选器使您能够在事件处理的事件捕获阶段处理事件。事件处理中的事件捕获阶段是事件通过调度链中所有节点的阶段。此调度链中的节点可以具有一个或多个过滤器,也可以根本没有过滤器来处理事件。
事件过滤器在此 Event Capturing 阶段处理事件,如鼠标事件、滚动事件、键盘事件等。但是,这些 Event Filters 需要向节点注册,以便为节点上生成的事件提供事件处理逻辑。
如果节点不包含事件筛选器,则事件将直接传递到目标节点。否则,单个筛选条件可用于多个节点和事件类型。简单地说,事件过滤器用于使父节点能够为其子节点提供通用处理;以及拦截事件并防止子节点对事件执行作。
添加和删除事件过滤器
要向节点添加事件过滤器,需要使用 Node 类的 addEventFilter() 方法注册此过滤器。
java">//Creating the mouse event handler
EventHandler<MouseEvent> eventHandler = new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent e) { System.out.println("Hello World"); circle.setFill(Color.DARKSLATEBLUE); }
};
//Adding event Filter
Circle.addEventFilter(MouseEvent.MOUSE_CLICKED, eventHandler);
同样,可以使用 removeEventFilter() 方法删除过滤器,如下所示
java">circle.removeEventFilter(MouseEvent.MOUSE_CLICKED, eventHandler);
例 1
下面是一个示例,演示了 JavaFX 中使用事件过滤器进行事件处理。将此代码保存在名为 EventFiltersExample.java 的文件中。
java">import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.event.EventHandler;import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle; import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage; public class EventFiltersExample extends Application { @Override public void start(Stage stage) { //Drawing a Circle Circle circle = new Circle(); //Setting the position of the circle circle.setCenterX(300.0f); circle.setCenterY(135.0f); //Setting the radius of the circle circle.setRadius(25.0f); //Setting the color of the circle circle.setFill(Color.BROWN); //Setting the stroke width of the circle circle.setStrokeWidth(20); //Setting the text Text text = new Text("Click on the circle to change its color"); //Setting the font of the text text.setFont(Font.font(null, FontWeight.BOLD, 15)); //Setting the color of the text text.setFill(Color.CRIMSON); //setting the position of the text text.setX(150); text.setY(50); //Creating the mouse event handler EventHandler<MouseEvent> eventHandler = new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent e) { System.out.println("Hello World"); circle.setFill(Color.DARKSLATEBLUE);} }; //Registering the event filter circle.addEventFilter(MouseEvent.MOUSE_CLICKED, eventHandler); //Creating a Group object Group root = new Group(circle, text); //Creating a scene object Scene scene = new Scene(root, 600, 300); //Setting the fill color to the scene scene.setFill(Color.LAVENDER); //Setting title to the Stage stage.setTitle("Event Filters Example"); //Adding scene to the stage stage.setScene(scene); //Displaying the contents of the stage stage.show(); } public static void main(String args[]){ launch(args); }
}
例 2
我们已经了解了事件过滤器如何处理鼠标事件。现在,让我们尝试在其他事件(如 Keyboard 事件)上注册事件过滤器。将此代码保存在名为 EventFilterKeyboard.java 的文件中。
java">import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.paint.Color;
import javafx.stage.Stage;public class EventFilterKeyboard extends Application{ @Override public void start(Stage primaryStage) throws Exception { //Adding Labels and TextFileds to the scene Label label1 = new Label("Insert Key"); Label label2 = new Label("Event"); label1.setTranslateX(100); label1.setTranslateY(100); label2.setTranslateX(100); label2.setTranslateY(150); TextField text1 = new TextField(); TextField text2 = new TextField(); text1.setTranslateX(250); text1.setTranslateY(100); text2.setTranslateX(250); text2.setTranslateY(150); //Creating EventHandler Object EventHandler<KeyEvent> filter = new EventHandler<KeyEvent>() { @Override public void handle(KeyEvent event) { text2.setText("Event : "+event.getEventType()); text1.setText(event.getText()); event.consume(); } }; //Registering Event Filter for the event generated on text field text1.addEventFilter(KeyEvent.ANY, filter); //Setting Group and Scene Group root = new Group(); root.getChildren().addAll(label1,label2,text1,text2); Scene scene = new Scene(root, 500, 300); primaryStage.setScene(scene); primaryStage.setTitle("Adding Event Filter"); primaryStage.show(); } public static void main(String[] args) { launch(args); }
}
JavaFX - 事件处理程序
事件处理程序使您能够在事件处理的事件冒泡阶段处理事件。
事件路由的冒泡阶段是事件从目标节点传输到阶段节点的阶段。与 Event filters 一样,节点可以有一个或多个处理程序,或者根本没有处理程序来处理事件。如果节点不包含处理程序,则事件将到达根节点,并且该过程完成。否则,如果事件调度链中的节点包含处理程序,则执行该处理程序。
单个处理程序可用于多个节点和多个事件类型。如果子节点的事件处理程序不使用该事件,则父节点的事件处理程序使父节点能够在子节点处理事件后对事件执行作,并为多个子节点提供通用事件处理。
添加和删除事件处理程序
要将事件处理程序添加到节点,您需要使用 Node 类的 addEventHandler() 方法注册此处理程序,如下所示
java">//Creating the mouse event handler
EventHandler<javafx.scene.input.MouseEvent> eventHandler = new EventHandler<javafx.scene.input.MouseEvent>() { @Override public void handle(javafx.scene.input.MouseEvent e) { System.out.println("Hello World"); circle.setFill(Color.DARKSLATEBLUE); }
};
//Adding the event handler
circle.addEventHandler(javafx.scene.input.MouseEvent.MOUSE_CLICKED, eventHandler);
同样,可以使用方法 removeEventHandler() 删除事件处理程序,如下所示
java">circle.removeEventHandler(MouseEvent.MOUSE_CLICKED, eventHandler);
例 1
下面的程序是一个示例,演示了如何使用事件处理程序在 JavaFX 中进行事件处理。
将此代码保存在名为 EventHandlersExample.java 的文件中。
java">import javafx.animation.RotateTransition;
import javafx.application.Application;
import javafx.event.EventHandler; import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;import javafx.scene.shape.Box;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import javafx.util.Duration; public class EventHandlersExample extends Application { @Override public void start(Stage stage) {//Drawing a Box Box box = new Box(); //Setting the properties of the Box box.setWidth(150.0); box.setHeight(150.0); box.setDepth(100.0); //Setting the position of the box box.setTranslateX(350); box.setTranslateY(150); box.setTranslateZ(50); //Setting the text Text text = new Text("Type any letter to rotate the box, and click on the box to stop the rotation"); //Setting the font of the text text.setFont(Font.font(null, FontWeight.BOLD, 15)); //Setting the color of the text text.setFill(Color.CRIMSON); //setting the position of the text text.setX(20); text.setY(50); //Setting the material of the box PhongMaterial material = new PhongMaterial(); material.setDiffuseColor(Color.DARKSLATEBLUE); //Setting the diffuse color material to box box.setMaterial(material); //Setting the rotation animation to the box RotateTransition rotateTransition = new RotateTransition(); //Setting the duration for the transition rotateTransition.setDuration(Duration.millis(1000)); //Setting the node for the transition rotateTransition.setNode(box); //Setting the axis of the rotation rotateTransition.setAxis(Rotate.Y_AXIS); //Setting the angle of the rotationrotateTransition.setByAngle(360); //Setting the cycle count for the transition rotateTransition.setCycleCount(50); //Setting auto reverse value to false rotateTransition.setAutoReverse(false); //Creating a text filed TextField textField = new TextField(); //Setting the position of the text field textField.setLayoutX(50); textField.setLayoutY(100); //Handling the key typed event EventHandler<KeyEvent> eventHandlerTextField = new EventHandler<KeyEvent>() { @Override public void handle(KeyEvent event) { //Playing the animation rotateTransition.play(); } }; //Adding an event handler to the text feld textField.addEventHandler(KeyEvent.KEY_TYPED, eventHandlerTextField); //Handling the mouse clicked event(on box) EventHandler<javafx.scene.input.MouseEvent> eventHandlerBox = new EventHandler<javafx.scene.input.MouseEvent>() { @Override public void handle(javafx.scene.input.MouseEvent e) { rotateTransition.stop(); } }; //Adding the event handler to the box box.addEventHandler(javafx.scene.input.MouseEvent.MOUSE_CLICKED, eventHandlerBox);//Creating a Group objectGroup root = new Group(box, textField, text); //Creating a scene object Scene scene = new Scene(root, 600, 300); //Setting camera PerspectiveCamera camera = new PerspectiveCamera(false); camera.setTranslateX(0); camera.setTranslateY(0); camera.setTranslateZ(0); scene.setCamera(camera); //Setting title to the Stage stage.setTitle("Event Handlers Example"); //Adding scene to the stage stage.setScene(scene); //Displaying the contents of the stage stage.show(); } public static void main(String args[]){ launch(args); }
}
在这里,如果您在文本字段中键入一个字母,则 3D 框将开始沿 x 轴旋转。如果再次单击该框,则旋转将停止。
例 2
让我们看看另一个可以使用 Event Handlers 的场景。在此示例中,我们将创建一个 JavaFX 对象(例如一个圆),并对其应用 Fade Transition。使用事件处理程序,我们指定何时需要播放 Transition 以及何时暂停;即通过单击按钮。
将此代码保存在名为 EventHandlersButton.java 的文件中。
java">import javafx.animation.ScaleTransition;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;public class EventHandlerButton extends Application{
@Override public void start(Stage primaryStage) throws Exception { // TODO Auto-generated method stub //Creating Circle and setting the color and stroke in the circle Circle c = new Circle(150, 125, 50); c.setFill(Color.RED); c.setStroke(Color.BLACK); //creating play button and setting coordinates for the button Button btn = new Button("Play"); btn.setTranslateX(100); btn.setTranslateY(250); // creating pause button and setting coordinate for the pause button Button btn1 = new Button("Pause"); btn1.setTranslateX(150); btn1.setTranslateY(250); //Instantiating TranslateTransition class to create the animation ScaleTransition st = new ScaleTransition(); //setting attributes for the TranslateTransitionst.setNode(c); st.setDuration(Duration.millis(1000)); st.setByX(1);st.setByY(1); st.setAutoReverse(true); st.setCycleCount(50);//Creating EventHandler EventHandler<MouseEvent> handler = new EventHandler() { @Override public void handle(MouseEvent event) { // TODO Auto-generated method stub if(event.getSource()==btn) { st.play(); //animation will be played when the play button is clicked } if(event.getSource()==btn1) { st.pause(); //animation will be paused when the pause button is clicked } event.consume(); } }; //Adding Handler for the play and pause button btn.setOnMouseClicked(handler); btn1.setOnMouseClicked(handler); // Creating Group Object Group root = new Group();root.getChildren().addAll(c, btn, btn1);// Creating Scene Object Scene scene = new Scene(root, 300, 300);primaryStage.setScene(scene);// Adding Title to ApplicationprimaryStage.setTitle("EventHandler Button"); primaryStage.show(); } public static void main(String[] args) { launch(args); }
}