事件驱动编程和动画
事件和事件源
(程序发生了某些事情的信号)
- 事件源对象:产生一个事件并且触发它的组件,即动作起源的地方。
- 事件对象:程序发生了某些事情的信号。
- 侦听器:能够接收事件源通知的对象。
- 事件处理器:用于处理事件的对象。
一个动作事件的处理器
- 注册一个事件源对象。
- 实现一个处理器接口:
如 buttonHandlerClass
- 对一个按钮注册一个ActionEvent处理器
例:
Button bt = new Button("OK");`
buttonHandlerClass handler = new buttonHandlerClass();
bt.setOnAction("handler");
内部类
(又称为嵌套类,是一个定义在另一个类范围中的类)
一个内部类可以引用定义在它所在的外部类中的数据和方法。
一个内部类被编译成一个名为OuterClassName$InnerClassName
例:类A是类B中的一个内部类,A的类文件名字是B$A.class
。
//inner class demo
public class OuterClass{
private int data;
//A method in the inner class
public void m(){
//do something
}
//An inner class
class InnerClass{
public void mi(){
//Directly reference data and method
//defined in its outer class
data++;
m();
}
}
}
- 个内部类可以使用可见性修饰符所定义,和应用于一个类中成员的可见性规则一样。
- 一个内部类可以被定义为static。一个static 的内部类可以作使用外部类的名字所访问。一个static 的内部类不能访问外部类类中非静态的成员。
- 内部类对象通常在外部类中所创建。但是你也可以从另外 一个类中来创建一个内部类的对象
- 如果内部类是非静态的, 你必须先创建一个外部类的实例,然后使用以下语法来创建一个内部类的对象:
OuterClass.InnerClass innerObject = outerObject.newInnerClass();
- 如果内部类是静态的,使用以下语法来创建一个内部类对象:
OuterClass.InnerClass innerObject = newOuterObject.InnerClass();
匿名内部类
一个匿名内部类是一个没有名字的内部类。它将一步实现定义一个内部类以及创建一个内部类的实例。语法如下:
new SuperClassName/Interface(){
//Implement or override methods in superclass or interface
//Other methods if necessary
}
- 一个若名内部类必须总是从一个父类继承或者实现一个接口,但是它不能有显式的extends 或者implements子。一个匿名内部类必须实现父类或者接口中的所有抽象方法。
- 一个匿名内部类总是使用它父类的无参构造方法来创建一个实例。如果一个若名内部类实现一个接口,构造方方法是Object().
- 一个匿名内部类被编译成一个名为OuterClassName$n. class的类。例如,如果外部类Test有两个匿名的内部类, 它们将被编译成Test$1.class 和Test$2.class。
使用lambda表达式简化事件处理
一个lambda表达式的基础语法是:
(type1 param1,type2 param2,...)->expression
(type1 param1,type2 param2,...)->statement
/*如果只有一个参数,并且没有显式的数据类型,圆括号可以被省略。
如果要编译器能理解lambda表达式,借口必须只包含一个抽象的方法
鼠标事件
对于一个鼠标按下、释放、单击、进入、退出、移动和拖动事件,使用什么方法来注册一个相应的处理器?
按下:setOnMousePressed(handler)
释放:setOnMouseReleased(handler)
单击:setOnMouseClicked(handler)
进入:setOnMouseEntered(handler)
退出:setOnMouseExited(handler)
移动:setOnMouseDragged(handler)
拖动:setOnMouseMoved(handler)
四个常数PRIMARY、SECONDARY、MIDDLE 和NONE 在MouseButton 中被定义,表示鼠标的左、右、中以及无按钮。可以使用getButton()方法来探测哪个按钮被按下。
例:getButton()==MouseButton.SECONDARY
表示右按钮被按下。
键盘事件
使用什么方法来针对键的按下、释放以及敲击事件注册处理器?
按下:setOnKeyPressed(handler)
释放:setOnKeyReleased(handler)
敲击:setOnKeyTyped(handler)
可观察对象的监听器
- 通过添加一个监听器来处理一个可观察对象中的值的变化。
- 一个 Observable 类的实例被认为是一个可观察对象,它包含了一个 addListener(InvalidationListener lister her) 方法用于添加监听器。
- 监听器类必须实现 InvalidationListener 接口以重写 invalidated(Observable o)方法,从而可以处理值的改变。
- 一旦 Observable 中的值改变了, 通过调用 invalida tecd(Observable o) 方法, 监听器得到通知。
添加监听器:addListener(InvalidationListener listener
监听器必须实现InvalidationListener接口以重写invalidated(Observable O)
动画
(抽象类 Animation 提供了 JavaFX 中动画制作的核心功能)
如何将一个动画的循环次数设置为无限次?如何自动倒转一个动画?如何开始、暂停以及停止一个动画?
animation.setCycleCount(Timeline.INFINITY);
animation.setAutoReverse(true);
animation.start();
animation.pause();
animation.stop();
PathTransition
PathTransition:制作一个在给定时间内, 节点沿着一条路径从一个端点到另外一个点的移动动画,PathTransition 是 Animation 的子类型。
/ Create a path transition
PathTransition pt = new PathTransition();// 创建一个 PathTransition
pt.setDuration(Duration.millis(4000));
pt.setPath(circle);
pt.setNode(rectangle);
pt.setOrientation(
PathTransition.OrientationType.ORTHOGONAL_TO_TANGENT);
pt.setCycleCount(Timeline.INDEFINITE);
pt.setAutoReverse(true);
pt.play(); // Start animation
FadeTransition
FadeTransition:在一个给定的时间内, 通过改变一个节点的透明度来产生动画。FadeTransition 是 Animation 的子类型。
FadeTransition ft = new FadeTransition(Duration.millis(4000),rectangle);
//创建一个 FadeTransition
ft.setFromValue(1.0);
ft.setToValue(0.1);
ft.setCycleCount(Timeline.INDEFINITE);
ft.setAutoReverse(true);
ft.play();
Timeline
Timeline:可以用于通过使用一个或者更多的KeyFrame (关键帧) 来编写任意动画。 每个 KeyFrame 在一个给定的时间间隔内顺序执行。 一个 KeyFrame 可以使用以下语句来构建: new KeyFrame(Duration.duration,EventHandler<ActionEvent> onFinished)
Timeline 继承自 Animation。
// Create an animation for alternating text
Timeline animation = new Timeline(
new KeyFrame(Duration.millis(500), eventHandler));
animation.setCycleCount(Timeline.INDEFINITE);
animation.play(); // Start animation
// Create a handler
EventHandler<ActionEvent> eventHandler = e -> {
if (text.getText().length() != 0) {
text.setText("");
}
else {
text.setText("Programming is fun");
}
};