宜兴网站开发/郑州粒米seo顾问
如何为同一对象的同一事件绑定多个处理器
问题
倘若类似编写下列代码,希望在点击时,既输出“这里执行第一种处理”又输出”这里执行第二种处理“
Circle circle = new Circle(100,100,50);
Pane pane = new Pane();
ObservableList<Node> list = pane.getChildren();
list.add(circle);
circle.setOnMousePressed(e->{
System.out.println("这里执行第一种处理");
});
circle.setOnMousePressed(e->{
System.out.println("这里执行第二种处理");
});
结果点击后控制台输出会是
后注册的处理器会覆盖之前注册的处理器
由那么怎么才能对同一对象的同一事件注册多个处理器呢?
解决方法
方法一(最优)
Circle circle = new Circle(100,100,50);
Pane pane = new Pane();
ObservableList<Node> list = pane.getChildren();
list.add(circle);
circle.addEventHandler(MouseEvent.MOUSE_PRESSED, e->{
System.out.println("这里执行第一种处理");
});
circle.addEventHandler(MouseEvent.MOUSE_PRESSED, e->{
System.out.println("这里执行第二种处理");
});
结果如下
至于为什么说这种方法最优,通过对比后最后解释。
方法二(其次)
至于既然setOn……只能绑定一个处理器,那么就把两种处理方式写进两个方法放进一个处理器中不就行了?(这里把原本省略的部分声明也写出来方便辨析)
public void start(stage primerStage){
Circle circle = new Circle(100,100,50);
Pane pane = new Pane();
ObservableList<Node> list = pane.getChildren();
list.add(circle);
circle.setOnMousePressed(e->{
handler1(circle);
handler2(circle);
});
Scene scene = new Scene(pane);
primerStage.setScene(scene);
primerStage.show();
}
//处理方法1
void handler1(Node node) {
System.out.println("这里执行第一种处理");
}
//处理方法2
void handler2(Node node) {
System.out.println("这里执行第二种处理");
}
结果如下
方法三(最次,次到不行)
说“次到不行”是因为局限性太大了,是一种对事件精准度要求不高的情况下,拿类似事件凑合的方法
Circle circle = new Circle(100,100,50);
Pane pane = new Pane();
ObservableList<Node> list = pane.getChildren();
list.add(circle);
circle.setOnMousePressed(e->{
System.out.println("这里执行第一种处理");
});
circle.setOnMouseClicked(e-> {
System.out.println("这里执行第二种处理");
});
说在要求不严格的情况下,“按下鼠标键”与“单击鼠标键”可以近似等同。因为这本质上是两种事件,自然不会出现“后绑定的处理器覆盖之前绑定的处理器”这种情况了。
但是尽量别用,因为还是有区别的,倘若我“按下鼠标键”却不松开,则只会出现"这里执行第一种处理"这种与预期不符的结果。
分析
为什么第一种方法最优?是与另外两种方法对比得出的,第三种方法局限性太大,自不必再赘述。关键是第二种方法不适用一种情况:
有一种需求,需要在某个操作之后,移除这个处理器
对于第二种方法而言,无能为力。因为两种处理方法放在同一个处理器中,移除时会两者都移除。若硬要实现,只能增加一个乍一看很莫名其妙的标记位,然后处理事件之前都先判别,这样代码可读性会严重下降。
而对于第一种方法只需这样做:
Circle circle = new Circle(100,100,50);
Pane pane = new Pane();
ObservableList<Node> list = pane.getChildren();
list.add(circle);
EventHandler<MouseEvent> handler1 = e->{
System.out.println("这里执行第一种处理");
};
EventHandler<MouseEvent> handler2 = e->{
System.out.println("这里执行第二种处理");
};
circle.addEventHandler(MouseEvent.MOUSE_PRESSED, handler1);
circle.addEventHandler(MouseEvent.MOUSE_PRESSED, handler2);
…………
(某个操作之后)
circle.removeEventHandler(MouseEvent.MOUSE_PRESSED,handler2);
注意:
相信你已经注意到了,在移除处理器这段代码中,我们没有用lambda表达式,因为removeEventHandle的第二个参数需要之前addEventHandler时的handler对象,而lambda、new constructor()这类匿名对象的方式显然没办法让我们再度使用该对象。
因此,为了程序的可扩展性,建议不要使用创建匿名对象的方式作为addEventHandler的第二个handler参数,除非你相当确定将来不会需要移除它