所以我有几个不同大小的Rectangle
个对象,名为r1
和r2
,最初出现在屏幕的死点。它们有不同的颜色(比如一个是红色而另一个是蓝色),较小的颜色放在较大的颜色上面,所以即使它们堆叠在中心,两者仍然可以区分。我希望他们四处移动并返回原来的位置,因此使用TranslateTransition
如下:
tt1 = new TranslateTransition(Duration.millis(20000), button1);
tt1.setByX(100); // moves 100 pixels to the right
tt1.setByY(-100); // moves 100 pixels down
tt1.setCycleCount(20); // oscillates 20 times
tt1.setAutoReverse(true);
tt2 = new TranslateTransition(Duration.millis(20000), button2);
tt2.setByX(-100); // moves 100 pixels to the left
tt2.setByY(100); // moves 100 pixels up
tt2.setCycleCount(20); // oscillates 20 times
tt2.setAutoReverse(true);
在移动过程中,如果r1
按下r2
和MouseEvent
中的任何一个,我希望它们消失几秒钟(比如说5秒钟)并且来又回来了。使用背景颜色完全是黑色的事实,我使用FillTransition
来实现这种效果:
FillTransition ft1 = new FillTransition(Duration.millis(5000), r1, Color.BLACK, Color.BLACK);
FillTransition ft2 = new FillTransition(Duration.millis(5000), r2, Color.BLACK, Color.BLACK);
通过将Rectangle
从Color.BLACK
转换为Color.BLACK
5秒钟,它会产生按钮已消失5秒的效果。此外,我在setOnMouseClicked
和r1
上有以下r2
,因此当用户输入时,它们会消失:
r1.setOnMouseClicked((MouseEvent t) -> {
ft1.play();
});
r2.setOnMouseClicked((MouseEvent t) -> {
ft2.play();
});
两个物体消失5秒后,它们必须重新出现在中心,就像它们在开始时一样,并使用tt1
和tt2
重复相同的摆动动作setOnFinished
和ft1
上的ft2
:
ft1.setOnFinished((ActionEvent event) -> {
r1.setFill(color1); // restore the original color
tt1.play();
});
ft2.setOnFinished((ActionEvent event) -> {
r2.setFill(color2); // restore the original color
tt2.play();
});
问题是,当r1
和r2
重新出现时,它们不是位于中心,而是位于它们最后消失的位置 - 换句话说,它们的位置重生是他们在检测到用户TranslateTransition
的最后MouseEvent
期间所处的位置。我尝试使用r1.setX(centerX)
和r1.setY(centerY)
对其进行修改,其中centerX
和centerY
是开头使用的原始中心坐标,但无法解决问题。实际上,当我使用r1.getX()
时,返回的值等于原始centerX
值,即使显而易见r1
未置于中心位置也是如此。这让我怀疑TranslateTransition
在不改变实际getX()
值的情况下履行职责。我还想过在ParallelTransition
和TranslateTransition
上以某种方式使用FillTransition
,因此tt1
可以在ft1
生效时完成,但从那时起ft1
<{1}}已经运行一段时间后会开始运行,它不会提供可行的解决方案。
所以我的问题是,如果某个对象tt1
在中间被中断,我该如何恢复该对象&#34;原始&#34;坐标,而不是TranslateTransition
被中断时对象最后被遗弃的位置?
P.S。我希望每次检测到TranslateTransition
时都避免创建新的Rectangle
个对象,因为这意味着所有MouseEvent
和TranslateTransition
都与FillTransition
和{{1}相关联必须重新创建。
答案 0 :(得分:1)
示例解决方案
运行程序,矩形将开始移动。点击矩形,它会暂时消失。在它消失后不久,矩形将重新出现在其原始起始位置并开始沿其原始轨迹移动。
import javafx.animation.*;
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Pauser extends Application {
@Override
public void start(Stage stage) throws Exception {
final Rectangle r1 = new Rectangle(
50, 150, 30, 30
);
final TranslateTransition tt1 = new TranslateTransition(
Duration.seconds(5),
r1
);
tt1.setFromX(0); // start at the layout origin for the node
tt1.setFromY(0); //
tt1.setByX(100); // moves 100 pixels to the right
tt1.setByY(-100); // moves 100 pixels down
tt1.setCycleCount(TranslateTransition.INDEFINITE);
tt1.setAutoReverse(true);
tt1.play();
final PauseTransition pt1 = new PauseTransition(
Duration.seconds(1)
);
pt1.setOnFinished(event -> {
tt1.playFromStart();
r1.setVisible(true);
});
r1.setOnMouseClicked(event -> {
r1.setVisible(false);
tt1.stop();
r1.setTranslateX(0);
r1.setTranslateY(0);
pt1.play();
});
stage.setScene(
new Scene(
new Group(r1),
200, 200
)
);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
这只是解决了一个矩形的问题。您可以将解决方案粘贴在循环中以处理多个矩形。
<强>观察强>
了解转化
屏幕上节点的位置基于应用于其布局位置的变换。布局位置保留在节点的layoutX / layoutY属性中。但是,如果您将转换转换应用于节点(正如您在TranslateTransition中隐式执行的那样),那么节点的屏幕位置将为layoutX + translateX / layoutY + translateY。
背景研究
所以关键是使用setFromX和setFromY从原始坐标开始。
将translateX / translateY值手动设置为0/0也是关键。如果没有这样做,节点将在开始从原点位置移动之前在其最后翻译位置闪烁。我认为这是因为从请求动画开始到实际开始并使用0/0的fromX / fromY坐标时会出现帧延迟。这是一种奇怪的行为。
答案 1 :(得分:0)
这对我来说很好。希望它是好方法。可能有新的类可以创建包含事件和转换的extends rectangle
。这只是两个rectangles
的示例。
import javafx.animation.FadeTransition;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
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 {
@Override
public void start(Stage primaryStage) throws Exception {
Rectangle rect1 = new Rectangle (100, 40, 120, 120);
rect1.setArcHeight(42);
rect1.setArcWidth(42);
rect1.setFill(Color.AQUA);
TranslateTransition tt1;
tt1 = new TranslateTransition(Duration.millis(3000), rect1);
tt1.setByX(200);
tt1.setByY(-200);
tt1.setCycleCount(2);
tt1.setAutoReverse(true);
tt1.play();
rect1.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent event) {
FadeTransition ft = new FadeTransition(Duration.millis(1000), rect1);
ft.setFromValue(1.0);
ft.setToValue(0.0);
ft.play();
event.consume();
}
});
tt1.setOnFinished(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
tt1.play();
FadeTransition ft = new FadeTransition(Duration.millis(1000), rect1);
ft.setToValue(1.0);
ft.play();
}
});
Rectangle rect2 = new Rectangle (100, 40, 80, 80);
rect2.setArcHeight(42);
rect2.setArcWidth(42);
rect2.setFill(Color.YELLOWGREEN);
TranslateTransition tt2;
tt2= new TranslateTransition(Duration.millis(6000), rect2);
tt2.setByX(-200);
tt2.setByY(200);
tt2.setCycleCount(2);
tt2.setAutoReverse(true);
tt2.play();
rect2.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent event) {
FadeTransition ft = new FadeTransition(Duration.millis(1000), rect2);
ft.setFromValue(1.0);
ft.setToValue(0.0);
ft.play();
event.consume();
}
});
tt2.setOnFinished(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
tt2.play();
FadeTransition ft = new FadeTransition(Duration.millis(1000), rect2);
ft.setToValue(1.0);
ft.play();
}
});
StackPane pane = new StackPane();
pane.setAlignment(Pos.CENTER);
pane.getChildren().addAll(rect1,rect2);
Scene scene = new Scene(pane, 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args){
launch(args);
}
}