JavaFX中onMouseExited失效:快速移开鼠标未触发退出动画
问题解决:JavaFX Pane鼠标快速移出时缩小动画不触发的修复方案
核心问题分析
你的代码存在三个关键问题导致快速移出鼠标时动画失效:
- 复用同一个
ScaleTransition实例,快速触发动画时状态冲突,导致后续动画无法正常执行 - 直接用
==比较浮点数(如currentScaleX ==1.0),动画执行后的缩放值是近似值,会导致判断条件失效 - 自定义
onMouseExited的逻辑完全错误:代码判断鼠标在principalPane内才执行缩小,与需求完全相反
修复步骤
1. 为每次动画创建独立的ScaleTransition实例
不要复用同一个动画对象,每次触发时新建实例避免状态冲突,同时修正浮点数判断逻辑:
public void scale1 () { // 用误差范围判断缩放值是否接近1.0,避免浮点数精度问题 if (Math.abs(pane1.getScaleX() - 1.0) < 0.01 && Math.abs(pane1.getScaleY() - 1.0) < 0.01) { ScaleTransition scale = new ScaleTransition(Duration.millis(100), pane1); scale.setByX(0.75); scale.setByY(0.75); scale.play(); } } public void scale1Re () { // 留误差范围判断缩放值是否大于初始状态 if (pane1.getScaleX() > 1.01 && pane1.getScaleY() > 1.01) { ScaleTransition scale = new ScaleTransition(Duration.millis(100), pane1); scale.setByX(-0.75); scale.setByY(-0.75); scale.play(); } }
2. 修正鼠标事件绑定逻辑
删除你自定义的错误onMouseExited处理器,直接通过Scene Builder将pane1的onMouseEntered绑定到scale1(),onMouseExited绑定到scale1Re()即可。如果需要代码绑定,使用以下正确逻辑:
@Override public void initialize(URL arg0, ResourceBundle arg1) { pane1.setOnMouseEntered(e -> scale1()); pane1.setOnMouseExited(e -> scale1Re()); }
注:
onMouseExited事件本身就是鼠标离开pane1时触发,不需要额外判断Bounds。
3. 可选优化:添加动画状态标记(防止重复触发)
如果需要避免快速连续触发动画导致的叠加问题,可以添加状态标记:
private boolean isAnimating = false; public void scale1 () { if (Math.abs(pane1.getScaleX() - 1.0) < 0.01 && !isAnimating) { isAnimating = true; ScaleTransition scale = new ScaleTransition(Duration.millis(100), pane1); scale.setByX(0.75); scale.setByY(0.75); scale.setOnFinished(e -> isAnimating = false); scale.play(); } } public void scale1Re () { if (pane1.getScaleX() > 1.01 && !isAnimating) { isAnimating = true; ScaleTransition scale = new ScaleTransition(Duration.millis(100), pane1); scale.setByX(-0.75); scale.setByY(-0.75); scale.setOnFinished(e -> isAnimating = false); scale.play(); } }
内容的提问来源于stack exchange,提问作者Crynda
相关产品推荐
相关产品推荐

