JavaFX字幕动画
您可能见过一些应用程序,当标签中的JavaFX字幕动画,java,animation,javafx,Java,Animation,Javafx,您可能见过一些应用程序,当标签中的字符串无法完全显示时,它会被设置为动画,并前后移动,以便用户可以看到标签中包含的字符串。当您的手机显示不足以显示整个标签时,安卓正在进行设置 下面是使用Service在JavaFX中实现它的代码,但这不是一个好方法 问题是: 下面是我如何使用动画或另一个内置JavaFX类来实现它的 代码: 导入javafx.application.Platform; 导入javafx.concurrent.Service; 导入javafx.concurrent.Task; 导
字符串无法完全显示时,它会被设置为动画,并前后移动,以便用户可以看到标签中包含的字符串。当您的手机显示不足以显示整个标签时,安卓正在进行设置
下面是使用Service
在JavaFX
中实现它的代码,但这不是一个好方法
问题是:
下面是我如何使用动画或另一个内置JavaFX类来实现它的
代码:
导入javafx.application.Platform;
导入javafx.concurrent.Service;
导入javafx.concurrent.Task;
导入javafx.scene.control.Label;
导入javafx.scene.paint.Color;
导入javafx.scene.text.Font;
导入javafx.scene.text.FontWeight;
导入工具.InfoTool;
公共类MoveTitleService扩展服务{
私有字符串标题;
可变布尔分布;
专用int计数器;
public Label movingText=新标签(“真正的YY大T形三通EXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX”);
/**
*建造师
*/
公共移动标题服务(){
movingText.setFont(Font.Font(“null”,fontwweight.BOLD,14));
movingText.setTextFill(颜色为白色);
设置成功(s->{
movingText.setText(“”);
});
}
//启动服务
public void startTheService(字符串标题){
this.title=标题;
doAnimation=true;
重启();
}
//停止服务
公共服务{
doAnimation=false;
}
@凌驾
受保护的任务createTask(){
返回新任务(){
@凌驾
受保护的Void调用()引发异常{
while(doAnimation){
//System.out.println(“MoveTitleService正在运行…”);
//一次一封信
对于(int m=0;m{
movingText.setText(title.substring(0,计数器)+addSpaces(title.length()-counter));
});
如果(!doAnimation)中断;
睡眠(150);
}
//向后消失
对于(int m=0;m{
movingText.setText(title.substring(counter));
});
如果(!doAnimation)中断;
睡眠(150);
}
//出现在前面
对于(int m=1;m{
movingText.setText(title.substring(title.length()-counter));
});
如果(!doAnimation)中断;
睡眠(150);
}
如果(!doAnimation)中断;
对于(int i=0;i,您可以使用时间线来进行此操作:
// min distance to Pane bounds
private static final double OFFSET = 25;
@Override
public void start(Stage primaryStage) {
Text text = new Text("A reallyyy big teeeeexxxxxxxxxxxxxxxxxxxxxxxt!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
text.setLayoutY(25);
text.setManaged(false);
text.setLayoutX(OFFSET);
Pane pane = new Pane(text);
pane.setMinHeight(50);
Timeline timeline = new Timeline();
KeyFrame updateFrame = new KeyFrame(Duration.seconds(1 / 60d), new EventHandler<ActionEvent>() {
private boolean rightMovement;
@Override
public void handle(ActionEvent event) {
double tW = text.getLayoutBounds().getWidth();
double pW = pane.getWidth();
double layoutX = text.getLayoutX();
if (2 * OFFSET + tW <= pW && layoutX >= OFFSET) {
// stop, if the pane is large enough and the position is correct
text.setLayoutX(OFFSET);
timeline.stop();
} else {
if ((rightMovement && layoutX >= OFFSET) || (!rightMovement && layoutX + tW + OFFSET <= pW)) {
// invert movement, if bounds are reached
rightMovement = !rightMovement;
}
// update position
if (rightMovement) {
layoutX += 1;
} else {
layoutX -= 1;
}
text.setLayoutX(layoutX);
}
}
});
timeline.getKeyFrames().add(updateFrame);
timeline.setCycleCount(Animation.INDEFINITE);
// listen to bound changes of the elements to start/stop the animation
InvalidationListener listener = o -> {
double textWidth = text.getLayoutBounds().getWidth();
double paneWidth = pane.getWidth();
if (textWidth + 2 * OFFSET > paneWidth
&& timeline.getStatus() != Animation.Status.RUNNING) {
timeline.play();
}
};
text.layoutBoundsProperty().addListener(listener);
pane.widthProperty().addListener(listener);
Scene scene = new Scene(pane);
primaryStage.setScene(scene);
primaryStage.show();
}
//到窗格边界的最小距离
专用静态最终双偏移=25;
@凌驾
公共无效开始(阶段primaryStage){
文本文本=新文本(“一个真正的YY大Teeeexxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
文本设置布局(25);
text.setManaged(false);
text.setLayoutX(偏移量);
窗格=新窗格(文本);
窗格玻璃设置最小高度(50);
时间线=新时间线();
KeyFrame UpdateName=新的关键帧(持续时间.s(1/60d),新的EventHandler(){
私权运动;
@凌驾
公共无效句柄(ActionEvent事件){
double tW=text.getLayoutBounds().getWidth();
double pW=pane.getWidth();
double layoutX=text.getLayoutX();
如果(2*OFFSET+tW=OFFSET){
//如果窗格足够大且位置正确,则停止
text.setLayoutX(偏移量);
timeline.stop();
}否则{
如果((rightMovement&&layoutX>=偏移量)| |(!rightMovement&&layoutX+tW+OFFSET{
double textWidth=text.getLayoutBounds().getWidth();
双窗格宽度=pane.getWidth();
如果(文本宽度+2*偏移量>窗格宽度
&&timeline.getStatus()!=Animation.Status.RUNNING){
timeline.play();
}
};
text.layoutbundsproperty().addListener(listener);
pane.widthProperty().addListener(listener);
场景=新场景(窗格);
初级阶段。场景(场景);
primaryStage.show();
}
请注意,需要自己重复更新位置,因为运行时无法调整动画
s,因此,要使任何大小调整在动画期间生效,需要重复更新…我收到一个错误“关键帧(持续时间,new EventHandler(){}未定义”在第31行..@GoXR3Plus:您是否添加了正确的导入,即导入javafx.animation.KeyFrame;导入javafx.event.ActionEvent;导入javafx.event.EventHandler;导入javafx.util.Duration;
?我在上面的代码中遇到了一些问题:)您能看看问题吗?谢谢您的回答。。。
// min distance to Pane bounds
private static final double OFFSET = 25;
@Override
public void start(Stage primaryStage) {
Text text = new Text("A reallyyy big teeeeexxxxxxxxxxxxxxxxxxxxxxxt!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
text.setLayoutY(25);
text.setManaged(false);
text.setLayoutX(OFFSET);
Pane pane = new Pane(text);
pane.setMinHeight(50);
Timeline timeline = new Timeline();
KeyFrame updateFrame = new KeyFrame(Duration.seconds(1 / 60d), new EventHandler<ActionEvent>() {
private boolean rightMovement;
@Override
public void handle(ActionEvent event) {
double tW = text.getLayoutBounds().getWidth();
double pW = pane.getWidth();
double layoutX = text.getLayoutX();
if (2 * OFFSET + tW <= pW && layoutX >= OFFSET) {
// stop, if the pane is large enough and the position is correct
text.setLayoutX(OFFSET);
timeline.stop();
} else {
if ((rightMovement && layoutX >= OFFSET) || (!rightMovement && layoutX + tW + OFFSET <= pW)) {
// invert movement, if bounds are reached
rightMovement = !rightMovement;
}
// update position
if (rightMovement) {
layoutX += 1;
} else {
layoutX -= 1;
}
text.setLayoutX(layoutX);
}
}
});
timeline.getKeyFrames().add(updateFrame);
timeline.setCycleCount(Animation.INDEFINITE);
// listen to bound changes of the elements to start/stop the animation
InvalidationListener listener = o -> {
double textWidth = text.getLayoutBounds().getWidth();
double paneWidth = pane.getWidth();
if (textWidth + 2 * OFFSET > paneWidth
&& timeline.getStatus() != Animation.Status.RUNNING) {
timeline.play();
}
};
text.layoutBoundsProperty().addListener(listener);
pane.widthProperty().addListener(listener);
Scene scene = new Scene(pane);
primaryStage.setScene(scene);
primaryStage.show();
}