JavaFX Canvas вращает изображение с фиксированным центром (и без отскока)
Я пытался запрограммировать мельницу с вращающимся ротором / головкой. Сам ствол фиксируется и рисуется в качестве фона на холсте (javafx). Сам ротор / головка - другое изображение. Я думал, что смогу повернуть само изображение и нарисовать его на графическом тексте. (Не сработало) Потом я попробовал разные вещи:
а. Рисуя изображение на другом холсте, вращайте холст, сделайте снимок этого холста. (Не работает)
б. Сделайте просмотр изображений, поверните просмотр изображений, сделайте снимок и нарисуйте его (не работает) и
с. Я пытался сделать RotateTransition (не работает). Теперь я вернулся к b: ImageView изображения, которое я вращаю.
б работы вроде, вроде! Это как-то "подпрыгивает", и я не знаю почему, потому что док говорит, что ImageView.setRotate (..) вращает изображение вокруг центра. Само изображение имеет одинаковую высоту и длину, поэтому оно должно подпрыгивать, как если бы это был прямоугольник. Я просто хочу, чтобы этот отскок прекратился... см. Здесь (ТАК не позволил мне опубликовать gif)
Все эти неудачные попытки пришли из чтения этого форума.
Исходный код здесь или в виде текста:
package sample;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import java.io.IOException;
public class Main extends Application {
private Pane root;
private Canvas canvas;
private GraphicsContext gc;
SnapshotParameters params = new SnapshotParameters();
private final Image stem = new Image(getClass().getResource("windrad.png").toExternalForm());
private final ImageView wheel = new ImageView(new Image(getClass().getResource("rad.png").toExternalForm()));
private final int height = 720;
private final int width = 720;
private final double distanceWidth = 400.0 / 720.0;
private final double distanceHeight = 240.0 / 720.0;
private int degrees = 0;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception{
params.setFill(Color.TRANSPARENT);
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(getClass().getResource("sample.fxml"));
try {
root = fxmlLoader.load();
canvas = (Canvas) fxmlLoader.getNamespace().get("canvas");
canvas.setHeight(height);
canvas.setWidth(width);
primaryStage.setHeight(height);
primaryStage.setWidth(width);
gc = canvas.getGraphicsContext2D();
} catch (IOException e) {
e.printStackTrace();
}
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root));
primaryStage.show();
animation().start();
}
private AnimationTimer animation() {
return new AnimationTimer() {
@Override
public void handle(long now) {
gc.clearRect(0,0, width, height);
gc.drawImage(stem, 0, 0);
degrees = degrees >= 360 ? 0 : ++degrees;
wheel.setRotate(degrees);
gc.drawImage(wheel.snapshot(params, null), width * distanceWidth - (int) wheel.getImage().getWidth() / 2, height * distanceHeight - (int) wheel.getImage().getHeight() / 2);
}
};
}
}
Итак, я получил это работает! @James_D мне очень помог. Вместо того, чтобы рисовать его на холсте, я поместил все объекты в сценограф и переместил его туда. Так как мой ротор / голова - это изображение, я смог использовать imageview.setRotate(). Моя проблема (для которой я разместил эту тему) возникла из-за использования холста. Я до сих пор не знаю, как возникла прыгающая ошибка, но цель моего проекта достигнута. Новый исходный код в ответах.
1 ответ
Я имел в виду размещать узлы в графе сцены вместо рисования на холсте. Конечно, вы (конечно) размещаете холст в графе сцены. Но по своей сути сложно изменить холст после его рисования. - @James_D
Этот комментарий помог и решил мою проблему. Новый исходный код указан в вопросе. Вместо того, чтобы рисовать его на холсте, я поместил все объекты в граф сцены и переместил изображение вместо холста или изображения. Вот новый исходный код:
package sample;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
public class Main extends Application {
private Group root;
private final ImageView stem = new ImageView(new Image(getClass().getResource("windrad.png").toExternalForm()));
private final ImageView wheel = new ImageView(new Image(getClass().getResource("rad.png").toExternalForm()));
private final int height = 720;
private final int width = 720;
private final double distanceWidth = 360.0 / 720.0;
private final double distanceHeight = 270.0 / 720.0;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception{
root = new Group();
root.getChildren().add(stem);
root.getChildren().add(wheel);
wheel.setX(width * distanceWidth - wheel.getImage().getWidth() / 2);
wheel.setY(height * distanceHeight - wheel.getImage().getHeight() / 2);
primaryStage.setTitle("Pinwheel");
primaryStage.setScene(new Scene(root));
primaryStage.show();
primaryStage.getIcons().add(new Image(getClass().getResource("windrad.png").toExternalForm()));
animation().start();
}
private AnimationTimer animation() {
return new AnimationTimer() {
@Override
public void handle(long now) {
wheel.setRotate(wheel.getRotate() + 1);
}
};
}
}