我目前正在開發一個小型 JavaFX 庫來顯示 svg 內容。我正在實作影片。他們正常作業,除了animate或animateTransformx和y的位置,我不明白為什么。
當我這樣做時,它可以完美地作業:
public class TimelineTest extends Application {
public static void main(String[] args) {
launch(args);
}
public void start(Stage primaryStage) {
Group root = new Group();
Scene scene = new Scene(root, 800, 600);
primaryStage.setScene(scene);
Rectangle rect = new Rectangle(100, 100, 50, 50);
root.getChildren().add(rect);
rect.setFill(Color.BLUE);
Timeline timeline = new Timeline();
KeyFrame kf0 = new KeyFrame(Duration.ZERO, new KeyValue(rect.xProperty(), 0));
KeyFrame kf1 = new KeyFrame(Duration.seconds(10), new KeyValue(rect.xProperty(), 100));
timeline.getKeyFrames().addAll(kf0, kf1);
timeline.play();
primaryStage.show();
}
}
但是當我在我的圖書館中做我認為完全相同的事情時,矩形似乎有點抽搐但并沒有真正移動。
我的代碼是:
WritableValue value = null;
switch (nodeName) {
case "rect":
Rectangle rect = (Rectangle) node;
switch (attrName) {
case X:
value = rect.xProperty();
break;
case Y:
value = rect.yProperty();
break;
case WIDTH:
value = rect.widthProperty();
break;
case HEIGHT:
value = rect.heightProperty();
break;
}
break;
}
Timeline timeline = new Timeline();
KeyValue fromValue = new KeyValue(value, 10);
KeyValue toValue = new KeyValue(value, 100);
KeyFrame fromFrame = new KeyFrame(Duration.ZERO, fromValue);
KeyFrame toFrame = new KeyFrame(Duration.seconds(10), toValue);
timeline.getKeyFrames().addAll(fromFrame, toFrame);
奇怪的是,當我對 width 或 height 屬性做同樣的事情時,它沒有任何問題。
我懷疑我的場景沒有正確創建(我檢查了我是否在平臺執行緒中執行所有這些),但其他一切都沒有任何問題。
如果我嘗試使用 aTranslateTransition代替,我會遇到完全相同的問題。
在這里對這個問題發表了一些評論之后,我現在不明白為什么我會遇到這個問題(但不知道如何解決它,至少現在是這樣)。我將 JavaFX 內容放在 ScrollPane 中。我不認為在這種情況下它會相關,但確實如此。代碼是:
VBox vBox = new VBox(node);
vBox.setAlignment(Pos.CENTER);
Group group = new Group(vBox );
StackPane content = new StackPane(group);
group.layoutBoundsProperty().addListener((observable, oldBounds, newBounds) -> {
content.setMinWidth(newBounds.getWidth());
content.setMinHeight(newBounds.getHeight());
});
ScrollPane scrollPane = new ScrollPane(content);
scrollPane.setPannable(true);
scrollPane.setFitToHeight(true);
scrollPane.setFitToWidth(true);
scrollPane.setPrefSize(500, 500);
我對 ScrollPane 使用了以下 StackOverflow 答案:JAVAFX zoom, scroll in ScrollPane
這是一個可重現的示例,顯示了所有內容:
public class TestAnimationInScroll extends Application {
public static void main(String[] args) {
launch(args);
}
public void start(Stage primaryStage) {
Rectangle rect = new Rectangle(100, 100, 50, 50);
rect.setFill(Color.BLUE);
Group root = new Group();
root.getChildren().add(rect);
VBox vBox = new VBox(root);
vBox.setAlignment(Pos.CENTER);
Group group = new Group(root);
StackPane content = new StackPane(group);
group.layoutBoundsProperty().addListener((observable, oldBounds, newBounds) -> {
content.setMinWidth(newBounds.getWidth());
content.setMinHeight(newBounds.getHeight());
});
ScrollPane scrollPane = new ScrollPane(content);
scrollPane.setPannable(true);
scrollPane.setFitToHeight(true);
scrollPane.setFitToWidth(true);
scrollPane.setPrefSize(500, 500);
Timeline timeline = new Timeline();
KeyFrame kf0 = new KeyFrame(Duration.ZERO, new KeyValue(rect.xProperty(), 0));
KeyFrame kf1 = new KeyFrame(Duration.seconds(10), new KeyValue(rect.xProperty(), 100));
timeline.getKeyFrames().addAll(kf0, kf1);
timeline.play();
content.setOnScroll(new EventHandler<ScrollEvent>() {
public void handle(ScrollEvent event) {
double zoomFactor = 1.05;
double deltaY = event.getDeltaY();
if (deltaY < 0) {
zoomFactor = 1 / zoomFactor;
}
Bounds groupBounds = group.getBoundsInLocal();
final Bounds viewportBounds = scrollPane.getViewportBounds();
double valX = scrollPane.getHvalue() * (groupBounds.getWidth() - viewportBounds.getWidth());
double valY = scrollPane.getVvalue() * (groupBounds.getHeight() - viewportBounds.getHeight());
group.setScaleX(group.getScaleX() * zoomFactor);
group.setScaleY(group.getScaleY() * zoomFactor);
Point2D posInZoomTarget = group.parentToLocal(new Point2D(event.getX(), event.getY()));
Point2D adjustment = group.getLocalToParentTransform().deltaTransform(posInZoomTarget.multiply(zoomFactor - 1));
scrollPane.layout();
scrollPane.setViewportBounds(groupBounds);
groupBounds = group.getBoundsInLocal();
scrollPane.setHvalue((valX adjustment.getX()) / (groupBounds.getWidth() - viewportBounds.getWidth()));
scrollPane.setVvalue((valY adjustment.getY()) / (groupBounds.getHeight() - viewportBounds.getHeight()));
}
});
Scene scene = new Scene(scrollPane, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
}
可以看到,可以放大ScrollPane,但是看不到影片效果。
如果我在相同的背景關系中使用 ScaleTransition,它會起作用,例如:
public class TestAnimationInScroll extends Application {
public static void main(String[] args) {
launch(args);
}
public void start(Stage primaryStage) {
Rectangle rect = new Rectangle(100, 100, 50, 50);
rect.setFill(Color.BLUE);
Group root = new Group();
root.getChildren().add(rect);
VBox vBox = new VBox(root);
vBox.setAlignment(Pos.CENTER);
Group group = new Group(root);
StackPane content = new StackPane(group);
group.layoutBoundsProperty().addListener((observable, oldBounds, newBounds) -> {
content.setMinWidth(newBounds.getWidth());
content.setMinHeight(newBounds.getHeight());
});
ScrollPane scrollPane = new ScrollPane(content);
scrollPane.setPannable(true);
scrollPane.setFitToHeight(true);
scrollPane.setFitToWidth(true);
scrollPane.setPrefSize(500, 500);
ScaleTransition transition = new ScaleTransition(Duration.seconds(5), rect);
transition.setFromX(1d);
transition.setFromY(1d);
transition.setToX(3d);
transition.setToY(3d);
transition.play();
content.setOnScroll(new EventHandler<ScrollEvent>() {
public void handle(ScrollEvent event) {
double zoomFactor = 1.05;
double deltaY = event.getDeltaY();
if (deltaY < 0) {
zoomFactor = 1 / zoomFactor;
}
Bounds groupBounds = group.getBoundsInLocal();
final Bounds viewportBounds = scrollPane.getViewportBounds();
double valX = scrollPane.getHvalue() * (groupBounds.getWidth() - viewportBounds.getWidth());
double valY = scrollPane.getVvalue() * (groupBounds.getHeight() - viewportBounds.getHeight());
group.setScaleX(group.getScaleX() * zoomFactor);
group.setScaleY(group.getScaleY() * zoomFactor);
Point2D posInZoomTarget = group.parentToLocal(new Point2D(event.getX(), event.getY()));
Point2D adjustment = group.getLocalToParentTransform().deltaTransform(posInZoomTarget.multiply(zoomFactor - 1));
scrollPane.layout();
scrollPane.setViewportBounds(groupBounds);
groupBounds = group.getBoundsInLocal();
scrollPane.setHvalue((valX adjustment.getX()) / (groupBounds.getWidth() - viewportBounds.getWidth()));
scrollPane.setVvalue((valY adjustment.getY()) / (groupBounds.getHeight() - viewportBounds.getHeight()));
}
});
Scene scene = new Scene(scrollPane, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
}
有人知道我的錯誤在哪里嗎?也許有一種方法仍然能夠在 scrollPane 中平移和縮放,但仍然可以正確地看到影片?
uj5u.com熱心網友回復:
我理解了這個問題:事實上,這是因為當孩子的位置或翻譯發生變化時,StackPane和Group都會自動更新它們的布局。解決方案是不允許這樣做。
它很簡單,Group因為它有一個setAutoSizeChildren(boolean)方法。
但我必須創建一個子類StackPane來做同樣的事情:
private class MyStackPane extends StackPane {
private boolean allowLayoutChildren = true;
private MyStackPane(Node root) {
super(root);
}
private void allowLayoutChildren(boolean allow) {
this.allowLayoutChildren = allow;
}
@Override
public void layoutChildren() {
if (allowLayoutChildren) {
super.layoutChildren();
}
}
}
那么完整的(作業)代碼是:
public class TestAnimationInScroll extends Application {
private Group root = null;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
Rectangle rect = new Rectangle(100, 100, 50, 50);
rect.setFill(Color.BLUE);
root = new Group();
root.getChildren().add(rect);
MyStackPane content = new MyStackPane(root);
root.layoutBoundsProperty().addListener((observable, oldBounds, newBounds) -> {
content.setMinWidth(newBounds.getWidth());
content.setMinHeight(newBounds.getHeight());
});
ScrollPane scrollPane = new ScrollPane(content);
scrollPane.setPannable(true);
scrollPane.setFitToHeight(true);
scrollPane.setFitToWidth(true);
scrollPane.setPrefSize(500, 500);
root.setAutoSizeChildren(false);
content.allowLayoutChildren(false);
Timeline timeline = new Timeline();
KeyFrame kf0 = new KeyFrame(Duration.ZERO, new KeyValue(rect.xProperty(), 0));
KeyFrame kf1 = new KeyFrame(Duration.seconds(10), new KeyValue(rect.xProperty(), 100));
timeline.getKeyFrames().addAll(kf0, kf1);
timeline.play();
content.setOnScroll(new EventHandler<ScrollEvent>() {
@Override
public void handle(ScrollEvent event) {
double zoomFactor = 1.05;
double deltaY = event.getDeltaY();
if (deltaY < 0) {
zoomFactor = 1 / zoomFactor;
}
Bounds groupBounds = root.getBoundsInLocal();
final Bounds viewportBounds = scrollPane.getViewportBounds();
double valX = scrollPane.getHvalue() * (groupBounds.getWidth() - viewportBounds.getWidth());
double valY = scrollPane.getVvalue() * (groupBounds.getHeight() - viewportBounds.getHeight());
root.setScaleX(root.getScaleX() * zoomFactor);
root.setScaleY(root.getScaleY() * zoomFactor);
Point2D posInZoomTarget = root.parentToLocal(new Point2D(event.getX(), event.getY()));
Point2D adjustment = root.getLocalToParentTransform().deltaTransform(posInZoomTarget.multiply(zoomFactor - 1));
scrollPane.layout();
scrollPane.setViewportBounds(groupBounds);
groupBounds = root.getBoundsInLocal();
scrollPane.setHvalue((valX adjustment.getX()) / (groupBounds.getWidth() - viewportBounds.getWidth()));
scrollPane.setVvalue((valY adjustment.getY()) / (groupBounds.getHeight() - viewportBounds.getHeight()));
}
});
Scene scene = new Scene(scrollPane, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
private class MyStackPane extends StackPane {
private boolean allowLayoutChildren = true;
private MyStackPane(Node root) {
super(root);
}
private void allowLayoutChildren(boolean allow) {
this.allowLayoutChildren = allow;
}
@Override
public void layoutChildren() {
if (allowLayoutChildren) {
super.layoutChildren();
}
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/372072.html
下一篇:滑動擴展影片旁邊的專案
