我正在研究一种元素周期表,有一个事件最终,当您将鼠标悬停时,会在所述元素上放大一点并显示更多信息,问题是它并没有真正做到这一点工作很好。可以说是跟踪,因为如果鼠标移动得有点快,或者很快离开位于边缘的面板,它就不会检测到鼠标的退出。 这是鼠标进入或退出时应执行的动画代码:
public void onScale(int i){
double currentScaleX = Panes[i].getScaleX();
double currentScaleY = Panes[i].getScaleY();//stores the current scale
if (currentScaleX == 1.0 && currentScaleY == 1.0) {//verify that said scale is the original (equal to 1)
TranslateTransition translate = new TranslateTransition(Duration.millis(50), Symbol[i]);
translate.setToY(-4);
translate.playFromStart();//move the symbol up a little
TranslateTransition tratn = new TranslateTransition(Duration.millis(50), AtomicNumber[i]);
tratn.setToY(-2);
tratn.playFromStart();
TranslateTransition tratm = new TranslateTransition(Duration.millis(50), AtomicMass[i]);
tratm.setToY(-2);
tratm.playFromStart();
TranslateTransition trnm = new TranslateTransition(Duration.millis(50), Name[i]);
trnm.setToY(3);
trnm.playFromStart();
AtomicMass[i].setVisible(true);
OxidationNumber[i].setVisible(true);//makes the atomic mass and oxidation number visible
ScaleTransition scale = new ScaleTransition(Duration.millis(100), Panes[i]);
scale.setToX(1.5);
scale.setToY(1.5);
scale.playFromStart();
//The panel is brought to the foreground, (note that this will not affect its position in the childlist unlike the .tofront method)
Panes[i].setViewOrder(-1.0);
Panes[i].getParent().setViewOrder(-1.0);
}
}
public void offScale(int i){
double currentScaleX = Panes[i].getScaleX();
double currentScaleY = Panes[i].getScaleY();
if (currentScaleX > 1.0 && currentScaleY > 1.0) {
TranslateTransition translate = new TranslateTransition(Duration.millis(50), Symbol[i]);
translate.setToY(0);
translate.playFromStart();
TranslateTransition tratn = new TranslateTransition(Duration.millis(50), AtomicNumber[i]);
tratn.setToY(0);
tratn.playFromStart();
TranslateTransition tratm = new TranslateTransition(Duration.millis(50), AtomicMass[i]);
tratm.setToY(0);
tratm.playFromStart();
TranslateTransition trnm = new TranslateTransition(Duration.millis(50), Name[i]);
trnm.setToY(0);
trnm.playFromStart();
AtomicMass[i].setVisible(false);
OxidationNumber[i].setVisible(false);
ScaleTransition scale = new ScaleTransition(Duration.millis(100), Panes[i]);
scale.setToX(1.0);
scale.setToY(1.0);
scale.playFromStart();
Panes[i].setViewOrder(0.0);
Panes[i].getParent().setViewOrder(0.0);
}
}
那么,你有什么建议吗?我正在使用窗格向量。 PS:我现在用来完成类似工作的方法是创建另一个方法,稍后在初始化整个表的另一个方法中调用该方法。 调用动画的方法:
@FXML
private void MouseEntered(MouseEvent event) {
Pane pane = (Pane) event.getSource();//creates a local variable based on the pane
onScale(Integer.parseInt(pane.getId()));
for(int i=1; i<=118; i++){
offScale(i);
}
}
@FXML
private void MouseExited(MouseEvent event) {
Pane pane = (Pane) event.getSource();
offScale(Integer.parseInt(pane.getId()));
}
在初始化方法的一部分中有一个循环,它分配如下事件:
Panes[i].setOnMouseEntered(this::MouseEntered);
Panes[i].setOnMouseExited(this::MouseExited);
MOUSE_ENTERED
和MOUSE_EXITED
事件应该始终被传递,无论您移动鼠标的速度如何或鼠标是否离开整个窗口。您没有提供一个最小的、完整的示例,所以我不能绝对确定问题是什么。然而,我相信问题是你正在为每个“方向”创建两个单独的动画。这意味着“按比例”动画可以与“非比例”动画并行运行,从而导致结果不一致。您应该使用单个动画并操纵其 rate
属性。如果您希望多个动画并行运行,我还建议您使用 ParallelTransition
,而不是单独播放每个动画。
例如:
import javafx.animation.Animation;
import javafx.animation.FadeTransition;
import javafx.animation.ParallelTransition;
import javafx.animation.ScaleTransition;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Main extends Application {
private static final int ROWS = 5;
private static final int COLUMNS = 5;
@Override
public void start(Stage primaryStage) throws Exception {
var root = new GridPane();
root.setPadding(new Insets(30));
root.setHgap(5);
root.setVgap(5);
root.setAlignment(Pos.CENTER);
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLUMNS; col++) {
int index = row * COLUMNS + col;
var cell = createCell(index);
root.add(cell, col, row);
}
}
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
private Node createCell(int index) {
var square = new Rectangle(75, 75, Color.WHITE);
square.setStroke(Color.BLACK);
square.setStrokeWidth(1);
var indexLabel = new Label(Integer.toString(index));
var moreInfoLabel = new Label("More info!");
moreInfoLabel.setOpacity(0);
var cell = new StackPane(square, indexLabel, moreInfoLabel);
installAnimations(indexLabel, moreInfoLabel, cell);
return cell;
}
private void installAnimations(Label indexLabel, Label moreInfoLabel, Node cell) {
var animation = new ParallelTransition(
createToCornerAnimation(indexLabel),
createFadeInAndOutAnimation(moreInfoLabel),
createScaleAnimation(cell));
animation.setOnFinished(e -> cell.setViewOrder(cell.isHover() ? -2 : 0));
cell.setOnMouseEntered(e -> {
e.consume();
cell.setViewOrder(-1);
animation.setRate(1); // forward
animation.play();
});
cell.setOnMouseExited(e -> {
e.consume();
cell.setViewOrder(-1);
animation.setRate(-1); // reverse
animation.play();
});
}
private Animation createToCornerAnimation(Node node) {
var animation = new TranslateTransition(Duration.millis(250), node);
animation.setFromX(0);
animation.setFromY(0);
animation.toXProperty().bind(node.layoutXProperty().negate().add(5));
animation.toYProperty().bind(node.layoutYProperty().negate().add(5));
return animation;
}
private Animation createFadeInAndOutAnimation(Node node) {
var animation = new FadeTransition(Duration.millis(250), node);
animation.setFromValue(0);
animation.setToValue(1);
return animation;
}
private Animation createScaleAnimation(Node node) {
var animation = new ScaleTransition(Duration.millis(250), node);
animation.setFromX(1.0);
animation.setFromY(1.0);
animation.setToX(1.5);
animation.setToY(1.5);
return animation;
}
}
输出: