多读书多实践,勤思考善领悟

JavaFX Event Handling(事件处理)

本文于1662天之前发表,文中内容可能已经过时。

在JavaFX中,我们可以开发GUI应用程序,Web应用程序和图形应用程序。在这样的应用程序中,每当用户与应用程序(节点)交互时,就说事件已经发生。

例如,单击按钮,移动鼠标,通过键盘输入字符,从列表中选择项目,滚动页面是导致事件发生的活动。

事件类型

这些事件大致可分为以下两类 -

  • Foreground Events 前景事件 - 需要用户直接交互的事件。它们是作为人与图形用户界面中的图形组件交互的结果而生成的。例如,单击按钮,移动鼠标,通过键盘输入字符,从列表中选择项目,滚动页面等。
  • Background Events 后台事件 - 需要最终用户交互的事件称为后台事件。操作系统中断,硬件或软件故障,计时器到期,操作完成是后台事件的示例。

JavaFX中的事件

JavaFX提供了处理各种事件的支持。类命名事件的包javafx.event是一个事件的基类。

任何子类的实例都是一个事件。JavaFX提供了各种各样的事件。其中一些列在下面。

  • Mouse Event 鼠标事件 - 这是单击鼠标时发生的输入事件。它由名为MouseEvent的类表示。它包括鼠标点击,鼠标按下,鼠标释放,鼠标移动,鼠标输入目标,鼠标退出目标等操作。
  • Key Event 键事件 - 这是一个输入事件,指示节点上发生的键击。它由名为KeyEvent的类表示。此事件包括按下键,释放键和键入键等操作。
  • Drag Event 拖动事件 - 这是拖动鼠标时发生的输入事件。它由名为DragEvent的类表示。它包括拖动输入,拖放,拖动输入目标,拖动退出目标,拖动等操作。
  • Window Event 窗口事件 - 这是与窗口显示/隐藏操作相关的事件。它由名为WindowEvent的类表示。它包括窗口隐藏,窗口显示,窗口隐藏,窗口显示等操作。

事件处理

事件处理是控制事件并决定事件发生时应该发生什么的机制。此机制具有代码,该代码称为事件发生时执行的事件处理程序。

JavaFX提供处理程序和过滤器来处理事件。在JavaFX中,每个事件都有 -

  • Target 目标 - 发生事件的节点。目标可以是窗口,场景和节点。
  • Source 源 - 生成事件的源将是事件的来源。在上面的场景中,鼠标是事件的来源。
  • Type 类型 - 发生事件的类型; 在鼠标事件的情况下 - 鼠标按下,鼠标释放是事件的类型。

假设我们有一个应用程序,其中包含使用组对象插入的Circle,Stop和Play Buttons,如下所示 -

样品申请

如果单击播放按钮,源将是鼠标,目标节点将是播放按钮,生成的事件类型是鼠标单击。

JavaFX中事件处理的阶段

每当生成事件时,JavaFX都会经历以下阶段。

路线建设

每当生成事件时,事件的默认/初始路由由构建事件调度链确定。它是从阶段到源节点的路径。

以下是当我们点击上述场景中的播放按钮时生成的事件的事件调度链。

播放按钮

事件捕获阶段

构建事件调度链后,应用程序的根节点将调度该事件。此事件将传递到调度链中的所有节点(从上到下)。如果这些节点中的任何节点具有为生成的事件注册的过滤器,则将执行该过滤器。如果调度链中没有节点具有生成事件的过滤器,则将其传递到目标节点,最后目标节点处理该事件。

事件冒泡阶段

在冒泡阶段,事件从目标节点传播到阶段节点(从下到上)。如果事件调度链中的任何节点具有为生成的事件注册的处理程序,则将执行该处理程序。如果这些节点都没有处理事件的处理程序,则事件到达根节点,最后完成该过程。

事件处理程序和过滤器

事件过滤器和处理程序包含处理事件的应用程序逻辑。节点可以注册到多个处理程序/过滤器。在父子节点的情况下,您可以为父节点提供公共过滤器/处理程序,它将作为所有子节点的默认处理。

如上所述,在事件期间,处理是执行的过滤器,并且在事件冒泡阶段期间,执行处理程序。所有处理程序和过滤器都实现了包javafx.event的接口EventHandler

添加和删除事件过滤器

要将事件过滤器添加到节点,您需要使用此方法注册这个过滤器addEventFilter()中的节点类。

1
2
3
4
5
6
7
8
9
10
//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()方法删除过滤器,如下所示 -

1
circle.removeEventFilter(MouseEvent.MOUSE_CLICKED, eventHandler);

事件处理示例

以下是使用事件过滤器演示JavaFX中的事件处理的示例。将此代码保存在名为EventFiltersExample.java的文件中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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);
}
}

使用以下命令从命令提示符编译并执行保存的java文件。

1
2
javac EventFiltersExample.java 
java EventFiltersExample

执行时,上面的程序生成一个JavaFX窗口,如下所示。

换颜色

添加和删除事件处理程序

到的事件处理程序添加到一个节点,则需要使用的方法来注册此处理的addEventHandler()的的节点类,如下所示。

1
2
3
4
5
6
7
8
9
10
11
12
//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()方法删除事件处理程序,如下所示 -

1
circle.removeEventHandler(MouseEvent.MOUSE_CLICKED, eventHandler);

以下程序是使用事件处理程序演示JavaFX中的事件处理的示例。

将此代码保存在名为EventHandlersExample.java的文件中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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 rotation
rotateTransition.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 object
Group 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);
}
}

使用以下命令从命令提示符编译并执行保存的java文件。

1
2
javac EventHandlersExample.java 
java EventHandlersExample

执行时,上面的程序生成一个显示文本字段和3D框的JavaFX窗口,如下所示 -

文本域

在这里,如果您在文本字段中键入字母,3D框将开始沿x轴旋转。如果再次单击该框,则旋转停止。

使用便捷方法进行事件处理

JavaFX中的一些类定义了事件处理程序属性。通过使用各自的setter方法将值设置为这些属性,您可以注册到事件处理程序。这些方法称为便利方法。

大多数这些方法存在于Node,Scene,Window等类中,并且它们可用于所有子类。

例如,要向按钮添加鼠标事件侦听器,可以使用方便方法setOnMouseClicked(),如下所示。

1
2
3
4
5
6
playButton.setOnMouseClicked((new EventHandler<MouseEvent>() { 
public void handle(MouseEvent event) {
System.out.println("Hello World");
pathTransition.play();
}
}));

以下程序是使用便捷方法演示JavaFX中的事件处理的示例。

将此代码保存在名为ConvinienceMethodsExample.java的文件中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
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 ConvinienceMethodsExample 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);
}
}

使用以下命令从命令提示符编译并执行保存的java文件。

1
2
javac ConvinienceMethodsExample.java 
java ConvinienceMethodsExample

执行时,上面的程序生成一个JavaFX窗口,如下所示。在此处单击播放按钮以启动动画,然后单击停止按钮以停止动画。

方便方法