java - JavaFX:事件 OnMouseExited 工作不正确
问题描述
我正在创建动画按钮,但有一个严重的问题 - 事件 OnMouseExited 工作不正确。
当我将鼠标悬停在按钮上时,速度不是很快 - 一切正常。但是当我快速悬停时 - OnMouseExited 事件不会触发。您可以在下面的视频中看到这种奇怪的行为。 https://youtu.be/Uz0vgIK21RU
这是我的代码:
public class MenuButton extends JFXButton {
private final int ICON_SIZE_MAX = 50;
private final int ICON_SIZE_MIN = 40;
private final int BUTTON_SIZE = 130;
private final int BUTTON_PANE_WIDTH = 114;
private final int BUTTON_PANE_HEIGHT = 122;
JFXButton btn = new JFXButton();
Pane p = new Pane();
GlyphIcon icon = null;
Label text = new Label();
public MenuButton(String name, FontAwesomeIcon fa_icon, EmojiOne eo_icon, String color, String rippler, VENTO.GUI gui) {
btn.setPrefWidth(BUTTON_SIZE);
btn.setPrefHeight(BUTTON_SIZE);
btn.setStyle("-fx-background-color: " + color + ";");
btn.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
btn.setRipplerFill(Paint.valueOf(rippler));
btn.setCursor(Cursor.HAND);
p.setPrefWidth(BUTTON_PANE_WIDTH);
p.setPrefHeight(BUTTON_PANE_HEIGHT);
if (fa_icon != null) {
icon = new FontAwesomeIconView(fa_icon);
} else if (eo_icon != null) {
icon = new EmojiOneView(eo_icon);
}
if (icon != null) {
icon.setGlyphSize(ICON_SIZE_MAX);
icon.setFill(Paint.valueOf("#ffffff"));
icon.setLayoutX(p.getPrefWidth() / 2 - icon.getGlyphSize().intValue() / 2);
icon.setLayoutY(p.getPrefHeight() / 2 - icon.getGlyphSize().intValue() / 2 + 43);
}
text.setText(name);
text.setFont(Font.font("System", FontWeight.BOLD, 18));
text.setTextFill(Paint.valueOf("#ffffff"));
text.setPrefWidth(p.getPrefWidth());
text.setLayoutX(0);
text.setLayoutY(75);
text.setAlignment(Pos.CENTER);
text.setOpacity(0);
p.getChildren().setAll(icon, text);
btn.setGraphic(p);
GlyphIcon finalIcon = icon;
btn.setOnMouseEntered(e -> {
if (finalIcon.getGlyphSize().intValue() != ICON_SIZE_MAX) {
return;
}
showMenuButton();
});
btn.setOnMouseExited(e -> {
if (finalIcon.getGlyphSize().intValue() != ICON_SIZE_MIN) {
return;
}
hideMenuButton();
});
btn.setOnAction(e -> {
//TODO
});
}
private void showMenuButton() {
Animation animation1 = new Timeline(new KeyFrame(Duration.millis(100), new KeyValue(icon.glyphSizeProperty(), ICON_SIZE_MIN)));
animation1.play();
Animation animation2 = new Timeline(new KeyFrame(Duration.millis(100), new KeyValue(icon.layoutXProperty(), p.getPrefWidth() / 2 - ICON_SIZE_MIN / 2)));
animation2.play();
Animation animation3 = new Timeline(new KeyFrame(Duration.millis(100), new KeyValue(icon.layoutYProperty(), p.getPrefHeight() / 2 - ICON_SIZE_MIN / 2 + 43 - 20)));
animation3.play();
Animation animation4 = new Timeline(new KeyFrame(Duration.millis(100), new KeyValue(text.opacityProperty(), 1.0)));
animation4.setDelay(Duration.millis(50));
animation4.play();
}
private void hideMenuButton() {
Animation animation4 = new Timeline(new KeyFrame(Duration.millis(50), new KeyValue(text.opacityProperty(), 0.0)));
animation4.play();
Animation animation3 = new Timeline(new KeyFrame(Duration.millis(50), new KeyValue(icon.layoutYProperty(), p.getPrefHeight() / 2 - ICON_SIZE_MAX / 2 + 43)));
animation3.setDelay(Duration.millis(25));
animation3.play();
Animation animation2 = new Timeline(new KeyFrame(Duration.millis(50), new KeyValue(icon.layoutXProperty(), p.getPrefWidth() / 2 - ICON_SIZE_MAX / 2)));
animation2.setDelay(Duration.millis(25));
animation2.play();
Animation animation1 = new Timeline(new KeyFrame(Duration.millis(50), new KeyValue(icon.glyphSizeProperty(), ICON_SIZE_MAX)));
animation1.setDelay(Duration.millis(25));
animation1.play();
}
}
而且我不知道该怎么办...希望有人可以帮助我。提前致谢。
解决方案
我认为这是因为在动画完成之前鼠标离开时你的动画会搞砸。解决此问题的一种方法是将动画存储在本地并相应地对其进行修改。例如
protected Animation animation;
protected void initAnimation()
{
this.animation = new ParallelTransition(
new Timeline(new KeyFrame(Duration.millis(100), new KeyValue(icon.glyphSizeProperty(), ICON_SIZE_MIN))),
new Timeline(new KeyFrame(Duration.millis(100), new KeyValue(icon.layoutXProperty(), p.getPrefWidth() / 2 - ICON_SIZE_MIN / 2))),
new Timeline(new KeyFrame(Duration.millis(100), new KeyValue(icon.layoutYProperty(), p.getPrefHeight() / 2 - ICON_SIZE_MIN / 2 + 43 - 20))),
new Timeline(new KeyFrame(Duration.millis(50)), new KeyFrame(Duration.millis(100), new KeyValue(text.opacityProperty(), 1.0))));
}
private void showMenuButtons()
{
// set animation to go foreward
this.animation.setRate(1.0);
// play from start when not running
if(this.animation.getStatus() != Animation.Status.RUNNING)
this.animation.playFromStart();
}
private void hideMenuButtons()
{
// set animation to go backwards
this.animation.setRate(-1.0);
// play from end when not running
if(this.animation.getStatus() != Animation.Status.RUNNING)
animation.playFrom(animation.getCycleDuration());
}
推荐阅读
- javascript - 单击另一支笔后,JavaScript Etch-a-Sketch 着色笔停止增加不透明度
- excel - HeaderRowRange 循环遍历所有标题并更改其值的问题
- android - 禁用在底部工作表模式上的拖动
- c - Linux中errno和返回码的区别
- c# - 如何使用 ReceiveAsync 在 Akka.NET Actor 中测试异步异常
- ffmpeg - 带有声音 ffmpeg 的循环覆盖输入视频
- nginx - Nginx pass_proxy 带变量
- javascript - 异步承诺返回未定义或区域感知承诺
- django - Django Filter Queries in List by last x Days with Timedelta 仅显示减去日期的查询,而不是完整范围
- javascript - 如何在 HTML 和 CSS 中创建一个全屏视频背景,我的所有组件都在它之上?