JavaFx 如何使用时间轴移动 window 位置
JavaFx how to move the window position with Timeline
我有这个舞台,当我展示它的时候。我希望它显示在屏幕底部,然后上升到中央屏幕。
就像一个通知。
我的代码
try {
Stage window = new Stage();
window.initModality(Modality.APPLICATION_MODAL);
window.setTitle(Message);
AnchorPane layout = (AnchorPane) FXMLLoader.load(Notification.class.getResource("window.fxml"));
Scene scene = new Scene(layout);
window.setScene(scene);
window.showAndWait();
} catch (Exception e) {
System.out.println(e);
}
您需要在 window 移动的地方添加一个计时器。这是因为 Window/Stage 只有 X 和 Y 值的 ReadOnlyProperties,因此您不能使用关键帧制作简单的时间轴动画。
您需要稍微调整一下 primaryScreenBounds 的高度和宽度,这样它就能满足您的需要。
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Screen;
import javafx.stage.Stage;
public class TimelineEvents extends Application {
private AnimationTimer timer;
Rectangle2D primaryScreenBounds = Screen.getPrimary().getVisualBounds();
double x = primaryScreenBounds.getMaxX() - 180;
double y = primaryScreenBounds.getMaxY() - 180;
double centerX = primaryScreenBounds.getWidth() / 2;
double centerY = primaryScreenBounds.getHeight() / 2;
double tickX = (x - centerX) / primaryScreenBounds.getWidth() * 10;
double tickY = (y - centerY) / primaryScreenBounds.getHeight() * 10;
@Override
public void start(Stage stage) {
Button btn = new Button();
btn.setText("Show Message");
btn.setOnAction((ActionEvent event) -> {
Label l = new Label("Message");
BorderPane root = new BorderPane(l);
Scene s = new Scene(root, 100, 100);
Stage window = new Stage();
window.setX(x);
window.setY(y);
timer = new AnimationTimer() {
@Override
public void handle(long l) {
x = x - tickX;
y = y - tickY;
if (x >= centerX) {
window.setX(x);
window.setY(y);
} else {
stop();
}
}
};
timer.start();
window.setScene(s);
window.showAndWait();
});
BorderPane pane = new BorderPane(btn);
Scene scene = new Scene(pane, 200, 200);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
专门为 Timeline
创建一个 属性,然后向其添加一个侦听器:
double startPos = ... ;
double endPos = ... ;
DoubleProperty y = new SimpleDoubleProperty(startPos);
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), new KeyValue(y, endPos)));
y.addListener((obs, oldValue, newValue) ->
window.setY(newValue.doubleValue()));
timeline.play();
SSCCE:
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Popup;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.util.Duration;
public class SlidingNotificationWindow extends Application {
@Override
public void start(Stage primaryStage) {
Button button = new Button("Show notification");
button.setOnAction(e -> {
Popup window = new Popup();
StackPane content = new StackPane(new Label("Notification"));
content.setStyle("-fx-background-color: aquamarine; -fx-padding: 40;");
content.setOnMouseClicked(evt -> window.hide());
window.getContent().add(content);
window.setWidth(120);
window.setHeight(75);
Rectangle2D primaryScreenBounds = Screen.getPrimary().getVisualBounds();
double startPos = primaryScreenBounds.getMaxY();
double endPos = 2*primaryScreenBounds.getMinY()/3 + primaryScreenBounds.getMaxY() / 3 ;
DoubleProperty y = new SimpleDoubleProperty(startPos);
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), new KeyValue(y, endPos)));
y.addListener((obs, oldValue, newValue) ->
window.setY(newValue.doubleValue()));
timeline.play();
window.setX(primaryScreenBounds.getMaxX() - 120);
window.show(primaryStage);
});
StackPane root = new StackPane(button);
primaryStage.setScene(new Scene(root, 350, 120));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
我有这个舞台,当我展示它的时候。我希望它显示在屏幕底部,然后上升到中央屏幕。 就像一个通知。
我的代码
try {
Stage window = new Stage();
window.initModality(Modality.APPLICATION_MODAL);
window.setTitle(Message);
AnchorPane layout = (AnchorPane) FXMLLoader.load(Notification.class.getResource("window.fxml"));
Scene scene = new Scene(layout);
window.setScene(scene);
window.showAndWait();
} catch (Exception e) {
System.out.println(e);
}
您需要在 window 移动的地方添加一个计时器。这是因为 Window/Stage 只有 X 和 Y 值的 ReadOnlyProperties,因此您不能使用关键帧制作简单的时间轴动画。
您需要稍微调整一下 primaryScreenBounds 的高度和宽度,这样它就能满足您的需要。
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Screen;
import javafx.stage.Stage;
public class TimelineEvents extends Application {
private AnimationTimer timer;
Rectangle2D primaryScreenBounds = Screen.getPrimary().getVisualBounds();
double x = primaryScreenBounds.getMaxX() - 180;
double y = primaryScreenBounds.getMaxY() - 180;
double centerX = primaryScreenBounds.getWidth() / 2;
double centerY = primaryScreenBounds.getHeight() / 2;
double tickX = (x - centerX) / primaryScreenBounds.getWidth() * 10;
double tickY = (y - centerY) / primaryScreenBounds.getHeight() * 10;
@Override
public void start(Stage stage) {
Button btn = new Button();
btn.setText("Show Message");
btn.setOnAction((ActionEvent event) -> {
Label l = new Label("Message");
BorderPane root = new BorderPane(l);
Scene s = new Scene(root, 100, 100);
Stage window = new Stage();
window.setX(x);
window.setY(y);
timer = new AnimationTimer() {
@Override
public void handle(long l) {
x = x - tickX;
y = y - tickY;
if (x >= centerX) {
window.setX(x);
window.setY(y);
} else {
stop();
}
}
};
timer.start();
window.setScene(s);
window.showAndWait();
});
BorderPane pane = new BorderPane(btn);
Scene scene = new Scene(pane, 200, 200);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
专门为 Timeline
创建一个 属性,然后向其添加一个侦听器:
double startPos = ... ;
double endPos = ... ;
DoubleProperty y = new SimpleDoubleProperty(startPos);
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), new KeyValue(y, endPos)));
y.addListener((obs, oldValue, newValue) ->
window.setY(newValue.doubleValue()));
timeline.play();
SSCCE:
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Popup;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.util.Duration;
public class SlidingNotificationWindow extends Application {
@Override
public void start(Stage primaryStage) {
Button button = new Button("Show notification");
button.setOnAction(e -> {
Popup window = new Popup();
StackPane content = new StackPane(new Label("Notification"));
content.setStyle("-fx-background-color: aquamarine; -fx-padding: 40;");
content.setOnMouseClicked(evt -> window.hide());
window.getContent().add(content);
window.setWidth(120);
window.setHeight(75);
Rectangle2D primaryScreenBounds = Screen.getPrimary().getVisualBounds();
double startPos = primaryScreenBounds.getMaxY();
double endPos = 2*primaryScreenBounds.getMinY()/3 + primaryScreenBounds.getMaxY() / 3 ;
DoubleProperty y = new SimpleDoubleProperty(startPos);
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), new KeyValue(y, endPos)));
y.addListener((obs, oldValue, newValue) ->
window.setY(newValue.doubleValue()));
timeline.play();
window.setX(primaryScreenBounds.getMaxX() - 120);
window.show(primaryStage);
});
StackPane root = new StackPane(button);
primaryStage.setScene(new Scene(root, 350, 120));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}