How can I center a JavaFX MeshView in a scene dynamically? - java

I'm writing a javafx image generator for .STL files. I'm using StlMeshImporter to import the STL file. However, when I import files in my javafx scene and try to take a snapshot, I get different result for each file because they are not center in the scene.
I would like to be able to scale it or center it, in the scene dynamically to take a snapshot. Is there a way to get the width and height of the object so I could set a scale factor, and offset automatically?
Here is my class:
public class STLImageGenerator extends Application {
private static final String MESH_FILENAME
= "./9sk02_flex_r02.stl";
private static final int VIEWPORT_SIZE = 800;
private static final double MODEL_SCALE_FACTOR = 3;
private static final double MODEL_X_OFFSET = 0;
private static final double MODEL_Y_OFFSET = 0;
private static final double MODEL_Z_OFFSET =0 ;
// private static final int VIEWPORT_SIZE = 4096;
private static final Color lightColor = Color.rgb(204, 204, 204);
private static final Color jewelColor = Color.rgb(0, 100, 204);
final static int CANVAS_WIDTH = 512;
final static int CANVAS_HEIGHT = 512;
private Group root;
private PointLight pointLight;
Canvas canvas = null;
PerspectiveCamera perspectiveCamera = null;
static MeshView[] loadMeshViews() {
File file = new File(MESH_FILENAME);
StlMeshImporter importer = new StlMeshImporter();
importer.read(file);
Mesh mesh = importer.getImport();
return new MeshView[]{new MeshView(mesh)};
}
private Group buildScene() {
MeshView[] meshViews = loadMeshViews();
System.out.println("MESHVIEWS: " + meshViews.length);
for (int i = 0; i < meshViews.length; i++) {
System.out.println("meshViews[i].getLayoutX():"+meshViews[i].getLayoutX());
meshViews[i].setScaleX(MODEL_SCALE_FACTOR);
meshViews[i].setScaleY(MODEL_SCALE_FACTOR);
meshViews[i].setScaleZ(MODEL_SCALE_FACTOR);
meshViews[i].setTranslateX((VIEWPORT_SIZE / 2) + MODEL_X_OFFSET-MODEL_SCALE_FACTOR);
meshViews[i].setTranslateY((VIEWPORT_SIZE / 2) + MODEL_Y_OFFSET-MODEL_SCALE_FACTOR);
meshViews[i].setTranslateZ((VIEWPORT_SIZE / 2) + MODEL_Z_OFFSET);
PhongMaterial sample = new PhongMaterial(jewelColor);
sample.setSpecularColor(lightColor);
sample.setSpecularPower(16);
meshViews[i].setMaterial(sample);
//meshViews[i].getTransforms().setAll(new Rotate(38, Rotate.Z_AXIS), new Rotate(20, Rotate.X_AXIS));
}
pointLight = new PointLight(lightColor);
pointLight.setTranslateX(VIEWPORT_SIZE * 3 / 4);
pointLight.setTranslateY(VIEWPORT_SIZE / 2);
pointLight.setTranslateZ(VIEWPORT_SIZE / 2);
PointLight pointLight2 = new PointLight(lightColor);
pointLight2.setTranslateX(VIEWPORT_SIZE * 1 / 4);
pointLight2.setTranslateY(VIEWPORT_SIZE * 3 / 4);
pointLight2.setTranslateZ(VIEWPORT_SIZE * 3 / 4);
PointLight pointLight3 = new PointLight(lightColor);
pointLight3.setTranslateX(VIEWPORT_SIZE * 5 / 8);
pointLight3.setTranslateY(VIEWPORT_SIZE / 2);
pointLight3.setTranslateZ(0);
Color ambientColor = Color.rgb(80, 80, 80, 0);
AmbientLight ambient = new AmbientLight(ambientColor);
root = new Group(meshViews);
root.getChildren().add(pointLight);
root.getChildren().add(pointLight2);
root.getChildren().add(pointLight3);
root.getChildren().add(ambient);
//root.setAutoSizeChildren(true);
return root;
}
private PerspectiveCamera addCamera(Scene scene) {
perspectiveCamera = new PerspectiveCamera();
System.out.println("Near Clip: " + perspectiveCamera.getNearClip());
System.out.println("Far Clip: " + perspectiveCamera.getFarClip());
System.out.println("FOV: " + perspectiveCamera.getFieldOfView());
perspectiveCamera.setFieldOfView(5);
scene.setCamera(perspectiveCamera);
return perspectiveCamera;
}
#Override
public void start(Stage primaryStage) {
//canvas = new Canvas(VIEWPORT_SIZE, VIEWPORT_SIZE);
Group group = buildScene();
Scene scene = new Scene(group, VIEWPORT_SIZE, VIEWPORT_SIZE, true, SceneAntialiasing.BALANCED);
scene.setFill(Color.rgb(255, 255, 255));
group.setAutoSizeChildren(true);
addCamera(scene);
//root.getChildren().add(canvas);
primaryStage.setMaxHeight(CANVAS_HEIGHT);
primaryStage.setMaxWidth(CANVAS_WIDTH);
String fname = MESH_FILENAME.substring(0, MESH_FILENAME.length() - 3) + "png";
File file = new File(fname);
primaryStage.setTitle("Jewel Viewer");
primaryStage.setScene(scene);
primaryStage.show();
try {
SnapshotParameters s = new SnapshotParameters();
// s.setCamera(perspectiveCamera);
// s.setViewport(Rectangle2D.EMPTY);
WritableImage wim = new WritableImage(1024, 1024);
scene.snapshot(wim);
// WritableImage writableImage = root.snapshot(new SnapshotParameters(), null);
RenderedImage renderedImage = SwingFXUtils.fromFXImage(wim, null);
ImageIO.write(renderedImage, "png", file);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
System.setProperty("prism.dirtyopts", "false");
Platform.setImplicitExit(false);
launch(args);
}

Related

How do I make the enemies of my game follow my character?

So I'm making a game where the enemies follow the player and the player kills them. How do I make the enemies' ImageViews follow the player.
I have tried some if sentences but I actually have no idea. I also searched everywhere but I only find other people doing it with Swing and I get really confused with a lot of things. I use Javafx btw.
public class Main extends Application{
private static final int HEIGHT = 720;
private static final int WIDTH = 1280;
Scene scene;
BorderPane root, htpLayout;
VBox buttons, paragraphs, images;
Button startButton, htpButton, htpReturnButton, leaderboardButton, exitButton;
Text gameName, paragraph1, paragraph2, paragraph3;
Pane gameLayout;
ImageView background;
Game game = new Game();
Player player = new Player();
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage window) throws Exception {
root = new BorderPane();
background = new ImageView("stick mob slayer background.png");
background.fitWidthProperty().bind(window.widthProperty());
background.fitHeightProperty().bind(window.heightProperty());
root.getChildren().add(background);
htpLayout = new BorderPane();
buttons = new VBox(15);
scene = new Scene(root, WIDTH, HEIGHT);
scene.getStylesheets().add("mobslayer/style.css");
gameName = new Text("Mob Slayer Unlimited");
gameName.setFont(Font.font("Complex", 50));
gameName.setFill(Color.WHITE);
root.setAlignment(gameName, Pos.CENTER_LEFT);
root.setTop(gameName);
startButton = new Button("Start Game");
startButton.setOnAction(e -> window.setScene(game.getScene()));
htpButton = new Button("How To Play");
htpButton.setOnAction(e -> scene.setRoot(htpLayout));
leaderboardButton = new Button("Leaderboard");
exitButton = new Button("Exit");
exitButton.setOnAction(e -> Platform.exit());
buttons.getChildren().addAll(startButton, htpButton, leaderboardButton, exitButton);
root.setCenter(buttons);
buttons.setAlignment(Pos.CENTER);
paragraphs = new VBox(30);
paragraph1 = new Text("Objektive\nNär spelet börjar kommer huvudkaraktären möta monster.\n"
+ "Ju längre in i spelet du kommer, ju fler och svårare monster dyker upp.\n"
+ "Ditt mål är att överleva så länge som möjligt.");
paragraph1.setFont(Font.font("Dubai", 13));
paragraph1.setFill(Color.BLACK);
paragraph2 = new Text("Movement\nAlla monster dras imot dig, så du måste akta dig.\n"
+ "Detta gör du med hjälp av piltangenterna.");
paragraph2.setFont(Font.font("Dubai", 13));
paragraph2.setFill(Color.BLACK);
paragraph3 = new Text("Special Effects\nDu kan också attackera tillbaka med en lätt attack(c)\n"
+ "eller med en specialattack(space) som dödar alla monster på skärmen.\n"
+ "Du kan dasha(x) för att röra dig snabbare åt ett håll.");
paragraph3.setFont(Font.font("Dubai", 13));
paragraph3.setFill(Color.BLACK);
paragraphs.getChildren().addAll(paragraph1, paragraph2, paragraph3);
htpReturnButton = new Button("Return");
htpReturnButton.setOnAction(e->scene.setRoot(root));
htpLayout.setBottom(htpReturnButton);
htpLayout.setAlignment(htpReturnButton,Pos.TOP_CENTER);
images = new VBox(30);
// Image image1 = new Image(new FileInputStream("resources\\cod zombies.jpg"));
// final ImageView image11 = new ImageView(image1);
// image11.setFitHeight(100);
// image11.setFitWidth(100);
// image11.setPreserveRatio(true);
//
// Image image2 = new Image(new FileInputStream("resources\\arrowkeys.png")) ;
// final ImageView image22 = new ImageView(image2);
// image22.setFitHeight(100);
// image22.setFitWidth(100);
// image22.setPreserveRatio(true);
//
// Image image3 = new Image(new FileInputStream("resources\\keys.png")) ;
// final ImageView image33 = new ImageView(image3);
// image33.setFitHeight(100);
// image33.setFitWidth(100);
// image33.setPreserveRatio(true);
//
// images.getChildren().addAll(image11, image22, image33);
//
paragraphs.setAlignment(Pos.TOP_LEFT);
htpLayout.setLeft(paragraphs);
htpLayout.setRight(images);
window.setTitle("Mob Slayer Unlimited");
window.setScene(scene);
window.setResizable(false);
window.show();
}
}
public class Game {
private static final int HEIGHT = 720;
private static final int WIDTH = 1280;
private Scene scene;
Pane root;
Text health, stamina, wave, kills;
int waveCounter = 1, killCounter = 0;
Button restartButton, pauseButton;
Line limitUp;
Player player = new Player();
Enemies enemy = new Enemies();
public Game() {
health = new Text(50, 30, "HP: " + player.getHealth());
health.setFont(Font.font("BankGothic Lt BT", 30));
health.setFill(Color.WHITE);
stamina = new Text(50, 80, "STAMINA: " + player.getStamina());
stamina.setFont(Font.font("BankGothic Lt BT", 30));
stamina.setFill(Color.WHITE);
wave = new Text(1050, 30, "WAVE: " + waveCounter);
wave.setFont(Font.font("BankGothic Lt BT", 30));
wave.setFill(Color.WHITE);
kills = new Text(1050, 80, "KILLS: " + killCounter);
kills.setFont(Font.font("BankGothic Lt BT", 30));
kills.setFill(Color.WHITE);
restartButton = new Button("RESTART");
restartButton.setFont(Font.font("BankGothic Lt BT", 30));
restartButton.setOnAction(e -> restart());
restartButton.setLayoutX(350);
restartButton.setLayoutY(20);
pauseButton = new Button("PAUSE");
pauseButton.setFont(Font.font("BankGothic Lt BT", 30));
pauseButton.setOnAction(e -> restart());
pauseButton.setLayoutX(650);
pauseButton.setLayoutY(20);
limitUp = new Line(0, 100, 1280, 100);
limitUp.setStroke(Color.WHITE);
root = new Pane(player.getSlayer(), limitUp, player.getSlayerHitbox(), health, stamina, wave, kills, restartButton, pauseButton, enemy.getEnemy());
root.setStyle("-fx-background-color: black");
enemy.enemyMovement();
movePlayerTo(WIDTH / 2, HEIGHT / 2);
scene = new Scene(root, WIDTH, HEIGHT);
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
switch (event.getCode()) {
case W: player.goUp = true; break;
case S: player.goDown = true; break;
case A: player.goLeft = true; break;
case D: player.goRight = true; break;
case K: player.running = true; break;
}
}
});
scene.setOnKeyReleased(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
switch (event.getCode()) {
case W: player.goUp = false; break;
case S: player.goDown = false; break;
case A: player.goLeft = false; break;
case D: player.goRight = false; break;
case K: player.running = false; break;
}
}
});
AnimationTimer timer = new AnimationTimer() {
#Override
public void handle(long now) {
int dx = 0, dy = 0;
if (player.goUp) dy -= 2;
if (player.goDown) dy += 2;
if (player.goRight) dx += 2;
if (player.goLeft) dx -= 2;
if (player.running) { dx *= 2; dy *= 2; }
enemy.enemyMovement();
movePlayerBy(dx, dy);
}
};
timer.start();
}
public Scene getScene() {
return scene;
}
// I took this methods for movement from Github
public void movePlayerBy(int dx, int dy) {
if (dx == 0 && dy == 0) return;
final double cx = player.getSlayer().getBoundsInLocal().getWidth() / 2;
final double cy = player.getSlayer().getBoundsInLocal().getHeight() / 2;
double x = cx + player.getSlayer().getLayoutX() + dx;
double y = cy + player.getSlayer().getLayoutY() + dy;
movePlayerTo(x, y);
}
public void movePlayerTo(double x, double y) {
final double cx = player.getSlayer().getBoundsInLocal().getWidth() / 2;
final double cy = player.getSlayer().getBoundsInLocal().getHeight() / 2;
if (x - cx >= 0 &&
x + cx <= WIDTH &&
y - cy >= 0 &&
y + cy <= HEIGHT) {
player.getSlayer().relocate(x - cx, y - cy);
player.getSlayerHitbox().relocate(x - cx + 37, y - cy + 35);
}
}
public class Player {
private int health;
private int damage;
private int stamina;
private Image slayerImage;
private ImageView slayer;
private Rectangle slayerHitbox;
boolean running, goUp, goDown, goRight, goLeft;
public Player () {
health = 5;
damage = 1;
stamina = 5;
slayerImage = new Image("stick mob slayer.png", 100, 100, true, true);
slayer = new ImageView(slayerImage);
slayerHitbox = new Rectangle(10, 50);
}
public int getDamage() {
return damage;
}
public void setDamage(int damage) {
this.damage = damage;
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
this.health = health;
}
public int getStamina() {
return stamina;
}
public void setStamina(int stamina) {
this.stamina = stamina;
}
public ImageView getSlayer() {
return slayer;
}
public Rectangle getSlayerHitbox() {
slayerHitbox.setFill(Color.TRANSPARENT);
return slayerHitbox;
}
}
public class Enemies {
private int health;
private int speed;
private Image enemyImage;
private ImageView enemy;
private Rectangle enemyHitbox;
Player player = new Player();
public Enemies () {
health = 1;
speed = 1;
enemyImage = new Image("stick enemy.png", 100, 100, true, true);
enemy = new ImageView(enemyImage);
enemyHitbox = new Rectangle(10, 50);
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
this.health = health;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public ImageView getEnemy () {
return enemy;
}
public Rectangle getEnemyHitbox() {
enemyHitbox.setFill(Color.YELLOW);
return enemyHitbox;
}
}
This is everything I have done so far. I would appreciate any help. If possible I would like to know how to make the enemies appear from random spots of the borders of the screen as well. Thanks in advance.
you should try first something more simple like implementing A* path search algo or some grid with some units on it before trying todo a game and having such questions

calculate size of detected object in tensorflow detect

i am making an app to detect 91 categories with help of tensorflow api. I want to show the size of the detected object ie. height* width for that i made following changes in my detectoractivity.java
i added,
float width = location.width();
float height = location.height();
float area = width * height;
String s = Float.toString(area);
TextView editText = (TextView) findViewById(R.id.tv);
editText.setText(s);
at line 322.
but it gives an error saying
Only the original thread that created a view hierarchy can touch its views.*
full code,
dtetctoractivity.java
public class DetectorActivity extends CameraActivity implements OnImageAvailableListener {
private static final Logger LOGGER = new Logger();
// Configuration values for the prepackaged multibox model.
private static final int MB_INPUT_SIZE = 224;
private static final int MB_IMAGE_MEAN = 128;
private static final float MB_IMAGE_STD = 128;
private static final String MB_INPUT_NAME = "ResizeBilinear";
private static final String MB_OUTPUT_LOCATIONS_NAME = "
output_locations/Reshape";
private static final String MB_OUTPUT_SCORES_NAME =
"output_scores/Reshape";
private static final String MB_MODEL_FILE =
"file:///android_asset/multibox_model.pb";
private static final String MB_LOCATION_FILE =
"file:///android_asset/multibox_location_priors.txt";
private static final int TF_OD_API_INPUT_SIZE = 300;
private static final String TF_OD_API_MODEL_FILE =
"file:///android_asset/ssd_mobilenet_v1_android_export.pb";
private static final String TF_OD_API_LABELS_FILE =
"file:///android_asset/coco_labels_list.txt";
// Configuration values for tiny-yolo-voc. Note that the graph is not included with TensorFlow and
// must be manually placed in the assets/ directory by the user.
// Graphs and models downloaded from http://pjreddie.com/darknet/yolo/ may be converted e.g. via
// DarkFlow (https://github.com/thtrieu/darkflow). Sample command:
// ./flow --model cfg/tiny-yolo-voc.cfg --load bin/tiny-yolo-voc.weights -
-savepb --verbalise
private static final String YOLO_MODEL_FILE = "file:///android_asset/graph-
tiny-yolo-voc.pb";
private static final int YOLO_INPUT_SIZE = 416;
private static final String YOLO_INPUT_NAME = "input";
private static final String YOLO_OUTPUT_NAMES = "output";
private static final int YOLO_BLOCK_SIZE = 32;
// Which detection model to use: by default uses Tensorflow Object Detection API frozen
// checkpoints. Optionally use legacy Multibox (trained using an older
version of the API)
// or YOLO.
private enum DetectorMode {
TF_OD_API, MULTIBOX, YOLO;
}
private static final DetectorMode MODE = DetectorMode.TF_OD_API;
// Minimum detection confidence to track a detection.
private static final float MINIMUM_CONFIDENCE_TF_OD_API = 0.6f;
private static final float MINIMUM_CONFIDENCE_MULTIBOX = 0.1f;
private static final float MINIMUM_CONFIDENCE_YOLO = 0.25f;
private static final boolean MAINTAIN_ASPECT = MODE == DetectorMode.YOLO;
private static final Size DESIRED_PREVIEW_SIZE = new Size(640, 480);
private static final boolean SAVE_PREVIEW_BITMAP = false;
private static final float TEXT_SIZE_DIP = 10;
private Integer sensorOrientation;
private Classifier detector;
private long lastProcessingTimeMs;
private Bitmap rgbFrameBitmap = null;
private Bitmap croppedBitmap = null;
private Bitmap cropCopyBitmap = null;
private boolean computingDetection = false;
private long timestamp = 0;
private Matrix frameToCropTransform;
private Matrix cropToFrameTransform;
private MultiBoxTracker tracker;
private byte[] luminanceCopy;
private BorderedText borderedText;
#Override
public void onPreviewSizeChosen(final Size size, final int rotation) {
final float textSizePx =
TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, TEXT_SIZE_DIP,
getResources().getDisplayMetrics());
borderedText = new BorderedText(textSizePx);
borderedText.setTypeface(Typeface.MONOSPACE);
tracker = new MultiBoxTracker(this);
int cropSize = TF_OD_API_INPUT_SIZE;
if (MODE == DetectorMode.YOLO) {
detector =
TensorFlowYoloDetector.create(
getAssets(),
YOLO_MODEL_FILE,
YOLO_INPUT_SIZE,
YOLO_INPUT_NAME,
YOLO_OUTPUT_NAMES,
YOLO_BLOCK_SIZE);
cropSize = YOLO_INPUT_SIZE;
} else if (MODE == DetectorMode.MULTIBOX) {
detector =
TensorFlowMultiBoxDetector.create(
getAssets(),
MB_MODEL_FILE,
MB_LOCATION_FILE,
MB_IMAGE_MEAN,
MB_IMAGE_STD,
MB_INPUT_NAME,
MB_OUTPUT_LOCATIONS_NAME,
MB_OUTPUT_SCORES_NAME);
cropSize = MB_INPUT_SIZE;
} else {
try {
detector = TensorFlowObjectDetectionAPIModel.create(
getAssets(), TF_OD_API_MODEL_FILE, TF_OD_API_LABELS_FILE, TF_OD_API_INPUT_SIZE);
cropSize = TF_OD_API_INPUT_SIZE;
} catch (final IOException e) {
LOGGER.e("Exception initializing classifier!", e);
Toast toast =
Toast.makeText(
getApplicationContext(), "Classifier could not be initialized", Toast.LENGTH_SHORT);
toast.show();
finish();
}
}
previewWidth = size.getWidth();
previewHeight = size.getHeight();
sensorOrientation = rotation - getScreenOrientation();
LOGGER.i("Camera orientation relative to screen canvas: %d", sensorOrientation);
LOGGER.i("Initializing at size %dx%d", previewWidth, previewHeight);
rgbFrameBitmap = Bitmap.createBitmap(previewWidth, previewHeight, Config.ARGB_8888);
croppedBitmap = Bitmap.createBitmap(cropSize, cropSize, Config.ARGB_8888);
frameToCropTransform =
ImageUtils.getTransformationMatrix(
previewWidth, previewHeight,
cropSize, cropSize,
sensorOrientation, MAINTAIN_ASPECT);
cropToFrameTransform = new Matrix();
frameToCropTransform.invert(cropToFrameTransform);
trackingOverlay = (OverlayView) findViewById(R.id.tracking_overlay);
trackingOverlay.addCallback(
new DrawCallback() {
#Override
public void drawCallback(final Canvas canvas) {
tracker.draw(canvas);
if (isDebug()) {
tracker.drawDebug(canvas);
}
}
});
addCallback(
new DrawCallback() {
#Override
public void drawCallback(final Canvas canvas) {
if (!isDebug()) {
return;
}
final Bitmap copy = cropCopyBitmap;
if (copy == null) {
return;
}
final int backgroundColor = Color.argb(100, 0, 0, 0);
canvas.drawColor(backgroundColor);
final Matrix matrix = new Matrix();
final float scaleFactor = 2;
matrix.postScale(scaleFactor, scaleFactor);
matrix.postTranslate(
canvas.getWidth() - copy.getWidth() * scaleFactor,
canvas.getHeight() - copy.getHeight() * scaleFactor);
canvas.drawBitmap(copy, matrix, new Paint());
final Vector<String> lines = new Vector<String>();
if (detector != null) {
final String statString = detector.getStatString();
final String[] statLines = statString.split("\n");
for (final String line : statLines) {
lines.add(line);
}
}
lines.add("");
lines.add("Frame: " + previewWidth + "x" + previewHeight);
lines.add("Crop: " + copy.getWidth() + "x" + copy.getHeight());
lines.add("View: " + canvas.getWidth() + "x" + canvas.getHeight());
lines.add("Rotation: " + sensorOrientation);
lines.add("Inference time: " + lastProcessingTimeMs + "ms");
borderedText.drawLines(canvas, 10, canvas.getHeight() - 10, lines);
}
});
}
OverlayView trackingOverlay;
#Override
protected void processImage() {
++timestamp;
final long currTimestamp = timestamp;
byte[] originalLuminance = getLuminance();
tracker.onFrame(
previewWidth,
previewHeight,
getLuminanceStride(),
sensorOrientation,
originalLuminance,
timestamp);
trackingOverlay.postInvalidate();
// No mutex needed as this method is not reentrant.
if (computingDetection) {
readyForNextImage();
return;
}
computingDetection = true;
LOGGER.i("Preparing image " + currTimestamp + " for detection in bg thread.");
rgbFrameBitmap.setPixels(getRgbBytes(), 0, previewWidth, 0, 0, previewWidth, previewHeight);
if (luminanceCopy == null) {
luminanceCopy = new byte[originalLuminance.length];
}
System.arraycopy(originalLuminance, 0, luminanceCopy, 0, originalLuminance.length);
readyForNextImage();
final Canvas canvas = new Canvas(croppedBitmap);
canvas.drawBitmap(rgbFrameBitmap, frameToCropTransform, null);
// For examining the actual TF input.
if (SAVE_PREVIEW_BITMAP) {
ImageUtils.saveBitmap(croppedBitmap);
}
runInBackground(
new Runnable() {
#Override
public void run() {
LOGGER.i("Running detection on image " + currTimestamp);
final long startTime = SystemClock.uptimeMillis();
final List<Classifier.Recognition> results = detector.recognizeImage(croppedBitmap);
lastProcessingTimeMs = SystemClock.uptimeMillis() - startTime;
cropCopyBitmap = Bitmap.createBitmap(croppedBitmap);
final Canvas canvas = new Canvas(cropCopyBitmap);
final Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(2.0f);
float minimumConfidence = MINIMUM_CONFIDENCE_TF_OD_API;
switch (MODE) {
case TF_OD_API:
minimumConfidence = MINIMUM_CONFIDENCE_TF_OD_API;
break;
case MULTIBOX:
minimumConfidence = MINIMUM_CONFIDENCE_MULTIBOX;
break;
case YOLO:
minimumConfidence = MINIMUM_CONFIDENCE_YOLO;
break;
}
final List<Classifier.Recognition> mappedRecognitions =
new LinkedList<Classifier.Recognition>();
for (final Classifier.Recognition result : results) {
final RectF location = result.getLocation();
if (location != null && result.getConfidence() >= minimumConfidence) {
canvas.drawRect(location, paint);
float width = location.width();
float height = location.height();
float area = width * height;
String s = Float.toString(area);
TextView editText = (TextView) findViewById(R.id.tv);
editText.setText(s);
cropToFrameTransform.mapRect(location);
result.setLocation(location);
mappedRecognitions.add(result);
}
}
tracker.trackResults(mappedRecognitions, luminanceCopy, currTimestamp);
trackingOverlay.postInvalidate();
requestRender();
computingDetection = false;
}
});
}
#Override
protected int getLayoutId() {
return R.layout.camera_connection_fragment_tracking;
}
#Override
protected Size getDesiredPreviewFrameSize() {
return DESIRED_PREVIEW_SIZE;
}
#Override
public void onSetDebug(final boolean debug) {
detector.enableStatLogging(debug);
}
}
The problem here is that you initiated the textview inside the wrong place.Beside that, you should never put this line :
TextView editText = (TextView) findViewById(R.id.tv);
inside a loop. Make your variables global : editText and width then you can implement a button and in the onClick method a toast will be shown with the last value given from the for loop.

JavaFx Stageshow 3 different stage

I have on 3 class , 3 stage and I want to do something like this: that I want to do show stage . One time I show 1st stage for 10 sec, next I show 2nd stage for 10 sec and next I show 3rd stage for 10 sec and next I show 1st .... But very important is this that the 3 stage have to work all time .
In swing I will be use CardLayout but here I don't know how do this.
code for one class:
public class SimpleSlideShowTest extends Application{
class SimpleSlideShow {
StackPane root = new StackPane();
ImageView[] slides;
public SimpleSlideShow() {
this.slides = new ImageView[4];
File file1 = new File("C:/Users/022/workspace22/EkranLCD/res/images/belka.png");
Image image1 = new Image(file1.toURI().toString());
File file = new File("C:/Users/022/workspace22/EkranLCD/res/images/kropka.png");
Image image2 = new Image(file.toURI().toString());
Image image3 = new Image(file1.toURI().toString());
Image image4 = new Image(file1.toURI().toString());
slides[0] = new ImageView(image1);
slides[1] = new ImageView(image2);
slides[2] = new ImageView(image3);
slides[3] = new ImageView(image4);
}
public StackPane getRoot() {
return root;
}
// The method I am running in my class
public void start() {
SequentialTransition slideshow = new SequentialTransition();
for (ImageView slide : slides) {
SequentialTransition sequentialTransition = new SequentialTransition();
FadeTransition fadeIn = getFadeTransition(slide, 0.0, 1.0, 0);
PauseTransition stayOn = new PauseTransition(Duration.millis(2000));
FadeTransition fadeOut = getFadeTransition(slide, 0, 0.0, 2000);
sequentialTransition.getChildren().addAll(fadeIn, stayOn, fadeOut);
slide.setOpacity(0);
this.root.getChildren().add(slide);
slideshow.getChildren().add(sequentialTransition);
}
slideshow.play();
}
// the method in the Transition helper class:
public FadeTransition getFadeTransition(ImageView imageView, double fromValue, double toValue, int durationInMilliseconds) {
FadeTransition ft = new FadeTransition(Duration.millis(durationInMilliseconds), imageView);
ft.setFromValue(fromValue);
ft.setToValue(toValue);
return ft;
}
}
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
SimpleSlideShow simpleSlideShow = new SimpleSlideShow();
Text msg = new Text("java2s.com d sad adas dsa sad dsa dsa dsa dsa sdasa dsa dsa");
msg.setFont(Font.font ("Verdana", 40));
msg.setY(Config.ySize-(Config.ySize/6));
Pane root1 = new Pane(msg);
root1.setLayoutX(Config.xSize/2);
root1.setLayoutY(Config.ySize-(Config.ySize/5));
root1.setPrefSize(Config.xSize/2,400);
Main2.start(msg);
simpleSlideShow.getRoot().getChildren().add(root1);
Scene scene = new Scene(simpleSlideShow.getRoot());
primaryStage.setScene(scene);
primaryStage.show();
simpleSlideShow.start();
}
}
My second class which I want to add
public class TestURLImage4 extends Application {
public static ArrayList<BusStop2> list = new ArrayList<>();
public static ArrayList<PositionTilesAndURLPaths> positionTilesAndURLPathsList = new ArrayList<>();
public static HashMap<String, Image> imgCache = new HashMap<>();
public static double lat;
public static double lon;
public static double deltaY;
public static double deltaX;
public static double positionX;
public static double positionY;
public static int[] imageCount = getCountImage();
public static int [] countImage = countImage();
public static int []x = new int [countImage[0]];
public static int []y = new int [countImage[1]];
private File file = new File("C:/Users/ElteGps 022/workspace22/EkranLCD/res/images/kropka.png");
private Image bus = new Image(file.toURI().toString());
public TestURLImage4() {
}
TestURLImage4(double lat, double lon){
int [] tiles= getTileNumber(lat, lon, Config.mapZoom);
deltaX = tile2lon(tiles[0] + 1 , Config.mapZoom) - tile2lon(tiles[0], Config.mapZoom);
deltaY = tile2lat(tiles[1], Config.mapZoom) - tile2lat(tiles[1] + 1 , Config.mapZoom);
positionX = (lon - tile2lon(tiles[0], Config.mapZoom)) * Config.imgSize/deltaX;
positionY = (tile2lat(tiles[1], Config.mapZoom) - lat) * Config.imgSize/deltaY;
getTiles(lat,lon);
getImgPositionAndURLsPath(list);
}
/**
* Method use to get count of image what we need
* #return
*/
private static int[] getCountImage(){
int xImageCount = (int) Math.ceil(Config.xSize/256);
int yImageCount = (int) Math.ceil(Config.ySize/256);
return new int[] {xImageCount, yImageCount};
}
/**
* Method use to get count of tiles
* #return
*/
public static int[] countImage(){
int xImageCount = imageCount[0];
int yImageCount = imageCount[1];
if(xImageCount-1 %2 != 0){
xImageCount = xImageCount + 2;
}
if(yImageCount-1 %2 != 0){
yImageCount = yImageCount + 2;
}
return new int[] {xImageCount, yImageCount};
}
/**
* Method use to get tiles
* #param lat
* #param lon
* #return
*/
private static ArrayList<BusStop2> getTiles(double lat, double lon ){
int [] numberTile = getTileNumber(lat, lon, Config.mapZoom);
int a1 = 1;
int a2 = 1;
int a3 = 1;
int a4 = 1;
x[0] = numberTile[0];
y[0] = numberTile[1];
for (int i = 1; i<x.length; i++){
if(i%2==0){
x[i] = numberTile[0]+(a1);
a1++;
}
else{
x[i] = numberTile[0]-(a2);
a2++;
}
}
for (int i = 1; i<y.length; i++){
if(i%2==0){
y[i] = numberTile[1]+(a3);
a3++;
}
else{
y[i] = numberTile[1]-(a4);
a4++;
}
}
for(int i = 0 ; i<x.length ; i++){
for (int j = 0 ;j<y.length ; j++ ){
list.add(new BusStop2(x[i], y[j], x[0] - x[i], y[0]-y[j]));
}
}
return list;
}
/**
*
* #param list
* #return
*/
private static ArrayList<PositionTilesAndURLPaths> getImgPositionAndURLsPath(ArrayList<BusStop2> list){
for(BusStop2 bus : list){
positionTilesAndURLPathsList.add(new PositionTilesAndURLPaths(256*bus.getX(), 256*bus.getY(),
Config.mapPath + "/" + bus.getA() + "/" + bus.getB() + ".png"));
}
return positionTilesAndURLPathsList;
}
public static int [] getTileNumber(final double lat, final double lon, final int zoom) {
int xtile = (int)Math.floor( (lon + 180) / 360 * (1<<zoom) ) ;
int ytile = (int)Math.floor( (1 - Math.log(Math.tan(Math.toRadians(lat)) + 1 / Math.cos(Math.toRadians(lat))) / Math.PI) / 2 * (1<<zoom) ) ;
if (xtile < 0)
xtile=0;
if (xtile >= (1<<zoom))
xtile=((1<<zoom)-1);
if (ytile < 0)
ytile=0;
if (ytile >= (1<<zoom))
ytile=((1<<zoom)-1);
return new int[] {xtile, ytile};
}
static double tile2lon(int x, int z) {
return x / Math.pow(2.0, z) * 360.0 - 180;
}
static double tile2lat(int y, int z) {
double n = Math.PI - (2.0 * Math.PI * y) / Math.pow(2.0, z);
return Math.toDegrees(Math.atan(Math.sinh(n)));
}
#Override
public void start(Stage stage) throws Exception {
Canvas canvas = new Canvas(Config.xSize, Config.ySize);
GraphicsContext gc = canvas.getGraphicsContext2D();
int [] aa =getTileNumber(51.401968,16.205556, 18);
getTiles(51.401968,16.205556);
getImgPositionAndURLsPath(list);
ExecutorService executor = Executors.newFixedThreadPool(10);
ArrayList<UtlToImageConverter> threadList = new ArrayList<>();
for(PositionTilesAndURLPaths url : positionTilesAndURLPathsList){
threadList.add(new UtlToImageConverter(url.getPath()));
}
try {
executor.invokeAll(threadList);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println(imgCache.size());
System.out.println( aa[0] + " " + aa[1] );
for(PositionTilesAndURLPaths pos : getImgPositionAndURLsPath(list)){
gc.drawImage(imgCache.get(pos.getPath()),Config.xSize/2-pos.getX()-Config.imgSize/2 ,(Config.ySize/2)- pos.getY()-Config.imgSize/2, Config.imgSize, Config.imgSize);
}
gc.drawImage(bus,Config.xSize/2-Config.imgSize/2-Config.markWidth/2+(int)positionX, Config.ySize/2+(int)positionY-Config.imgSize/2-Config.markHeight/2, Config.markWidth, Config.markHeight);
Pane root = new Pane();
root.getChildren().add(canvas);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args)
{
Application.launch(args);
}
}

Scrollpane strange scaling in libgdx

The text drawn by font and drawn in List inside Scrollpane seem with different sizes. This is how I draw text:
font.draw(batch, "score", 500, 700);
And how I draw text in List inside ScrollPane:
tfBackground = new Texture(Gdx.files.internal("tfbackground.png"));
knob_scroll = new Texture(Gdx.files.internal("knob_scroll.png"));
scroll_horizontal = new Texture(Gdx.files.internal("scroll_horizontal.png"));
sps.background = new TextureRegionDrawable(new TextureRegion(tfBackground));
sps.vScroll = new TextureRegionDrawable(new TextureRegion(scroll_horizontal));
sps.vScrollKnob = new TextureRegionDrawable(new TextureRegion(knob_scroll));
listS = new List.ListStyle();
listS.font = font;
listS.fontColorSelected = Color.BLACK;
listS.fontColorUnselected = Color.GRAY;
listS.selection = new TextureRegionDrawable(new TextureRegion(tfBackground));
scoreList = new List<String>(listS);
items = new Array<String>();
res += "score 1, score 2, score 3, score 4, score 5, score 6, score 7, score 8, score 9, score 10";
String name_score[] = res.split(",");
for(String s: name_score)
{
items.add(s);
}
scoreList.setItems(items);
scoreList.pack();
scrollPane = new ScrollPane(scoreList, sps);
addActor(scrollPane);
And this is the weird(?) result:
It seems that scrollpane is scaling somehow. I don't want it the text inside scrollpane to be scaled.
This is the whole code:
public class ResultScreen extends AbstractScreen{
private OrthographicCamera camera;
private Viewport viewport;
private BitmapFont font;
private SpriteBatch batch;
private String res;
private float time = 10;
private Texture tfBackground, knob_scroll, scroll_horizontal;
private List<String> scoreList;
private ScrollPane scrollPane;
private List.ListStyle listS;
private ScrollPane.ScrollPaneStyle sps;
private Array<String> items;
public ResultScreen(float time, String res) {
this.time = time;
font = new BitmapFont(Gdx.files.internal("aw.fnt"));
font.setColor(Color.BLACK);
camera = new OrthographicCamera();
viewport = new StretchViewport(800, 1024, camera);
//viewport = new FitViewport(1240, 800, camera);
batch = new SpriteBatch();
camera.position.x = 400;
camera.position.y = 512;
viewport.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
this.res = res;
fillList();
}
#Override
public void buildStage() {
// TODO Auto-generated method stub
}
#Override
public void resize(int width, int height) {
viewport.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
}
#Override
public void render(float delta) {
super.render(delta);
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
font.draw(batch, "score", 500, 700);
batch.end();
draw();
act();
}
private void fillList()
{
sps = new ScrollPane.ScrollPaneStyle();
tfBackground = new Texture(Gdx.files.internal("tfbackground.png"));
knob_scroll = new Texture(Gdx.files.internal("knob_scroll.png"));
scroll_horizontal = new Texture(Gdx.files.internal("scroll_horizontal.png"));
sps.background = new TextureRegionDrawable(new TextureRegion(tfBackground));
sps.vScroll = new TextureRegionDrawable(new TextureRegion(scroll_horizontal));
sps.vScrollKnob = new TextureRegionDrawable(new TextureRegion(knob_scroll));
listS = new List.ListStyle();
listS.font = font;
listS.fontColorSelected = Color.BLACK;
listS.fontColorUnselected = Color.GRAY;
listS.selection = new TextureRegionDrawable(new TextureRegion(tfBackground));
scoreList = new List<String>(listS);
items = new Array<String>();
res += "score 1, score 2, score 3, score 4, score 5, score 6, score 7, score 8, score 9, score 10";
String name_score[] = res.split(",");
for(String s: name_score)
{
items.add(s);
}
scoreList.setItems(items);
scoreList.pack();
scrollPane = new ScrollPane(scoreList, sps);
scrollPane.setWidth(300);
System.out.println(Gdx.graphics.getWidth());
addActor(scrollPane);
}
}
PS: Abstract screen extends Stage and implements Screen.
Your constructor doesn't call through to a superclass constructor, which would also need to call through to one of the Stage constructors to make sure your Stage is properly set up.
What's going on here is that you set up a camera and viewport (and SpriteBatch, although not part of the issue) that are used only for your font.draw and are distinct from what the Stage uses.
Your class needs to look something like this:
public class ResultScreen extends AbstractScreen{
private OrthographicCamera camera;
private Viewport viewport;
private BitmapFont font;
private Batch batch; //<------------changed
private String res;
private float time = 10;
private Texture tfBackground, knob_scroll, scroll_horizontal;
private List<String> scoreList;
private ScrollPane scrollPane;
private List.ListStyle listS;
private ScrollPane.ScrollPaneStyle sps;
private Array<String> items;
public ResultScreen(float time, String res) {
super(new StretchViewport(800, 1024)); //Call an AbstractScreen constructor that calls a Stage constructor
this.time = time;
font = new BitmapFont(Gdx.files.internal("aw.fnt"));
font.setColor(Color.BLACK);
camera = getCamera(); //<------------changed
viewport = getViewport(); //<------------changed
batch = getBatch(); //<------------changed
camera.position.x = 400;
camera.position.y = 512;
// unnecessary can remove because this is called in resize: viewport.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
this.res = res;
fillList();
}
}
For example, AbstractScreen could have a constructor like this:
public AbstractScreen(Viewport viewport){
super(viewport);
}

How to animate LinearGradient on JavaFX?

I am trying to animate the text fill of a Label on JavaFX (Using JavaFX 8).
My goal is to make the First color of the gradient to change from yellow to red every half second.
I have tried this:
Timeline timeline = new Timeline();
timeline.setCycleCount(Animation.INDEFINITE);
timeline.setAutoReverse(true);
LinearGradient fill1 = new LinearGradient(50,50,200,200,false, CycleMethod.NO_CYCLE, new Stop(0.1f, Color.YELLOW), new Stop(1.0f, Color.BLACK));
LinearGradient fill2 = new LinearGradient(50,50,200,200,false, CycleMethod.NO_CYCLE, new Stop(0.1f, Color.RED), new Stop(1.0f, Color.BLACK));
KeyValue keyValue1 = new KeyValue(labelInstrucoes.textFillProperty(), fill1, Interpolator.EASE_OUT);
KeyValue keyValue2 = new KeyValue(labelInstrucoes.textFillProperty(), fill2, Interpolator.EASE_OUT);
KeyFrame keyframe1 = new KeyFrame(Duration.millis(0), keyValue1);
KeyFrame keyframe2 = new KeyFrame(Duration.millis(500), keyValue2);
timeline.getKeyFrames().addAll(keyframe1, keyframe2);
timeline.play();
But it didn't work. However, if instead of LinearGradient i use a simple color, like this:
KeyValue keyValue1 = new KeyValue(labelInstrucoes.textFillProperty(), Color.YELLOW, Interpolator.EASE_OUT);
KeyValue keyValue2 = new KeyValue(labelInstrucoes.textFillProperty(), Color.RED, Interpolator.EASE_OUT);
It works. So, how to animate the gradient?
You can use a css trick for this, using looked-up colors.
In an external CSS file, define a looked-up color for the beginning of the linear gradient, and define the text fill using a linear gradient that references the looked-up color:
animated-gradient.css:
.animated-gradient {
-gradient-base: red ;
-fx-text-fill: linear-gradient(to right, -gradient-base, black);
}
Then "animate" a color property, and update the inline style to change the value of the looked-up color whenever the property changes:
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;
public class AnimatedGradient extends Application {
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
Label label = new Label("Animated gradient");
root.getChildren().add(label);
label.getStyleClass().add("animated-gradient");
Scene scene = new Scene(root,400,400);
scene.getStylesheets().add(getClass().getResource("animated-gradient.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
ObjectProperty<Color> baseColor = new SimpleObjectProperty<>();
KeyValue keyValue1 = new KeyValue(baseColor, Color.RED);
KeyValue keyValue2 = new KeyValue(baseColor, Color.YELLOW);
KeyFrame keyFrame1 = new KeyFrame(Duration.ZERO, keyValue1);
KeyFrame keyFrame2 = new KeyFrame(Duration.millis(500), keyValue2);
Timeline timeline = new Timeline(keyFrame1, keyFrame2);
baseColor.addListener((obs, oldColor, newColor) -> {
label.setStyle(String.format("-gradient-base: #%02x%02x%02x; ",
(int)(newColor.getRed()*255),
(int)(newColor.getGreen()*255),
(int)(newColor.getBlue()*255)));
});
timeline.setAutoReverse(true);
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
}
public static void main(String[] args) {
launch(args);
}
}
(You can use Bindings.format(...) instead of the listener, not much difference.)
Here is a solution without css. It can be used in animated Controls.
Below I posted the code of Application with two different elements. You can run it and see how it works.
1. This is Region with animated Background
public class FilledRegion extends Region {
private final Random rand;
private ObjectProperty<Color> externalColor = new SimpleObjectProperty();
private ObjectProperty<Color> internalColor = new SimpleObjectProperty();
private Color oldExternalColor;
private Color oldInternalColor;
private Background bg;
private Timeline timeline;
private int duration;
public FilledRegion() {
rand = new Random();
this.setMinWidth(75);
oldExternalColor = getRandomColor(AnimatedGradients.baseExternalColor, AnimatedGradients.externalDelta);
oldInternalColor = getRandomColor(AnimatedGradients.baseInternalColor, AnimatedGradients.internalDelta);
externalColor.set( oldExternalColor );
internalColor.set( oldInternalColor );
setBackground();
internalColor.addListener((obs, oldColor, newColor) -> {
setBackground();
});
}
public void startAnimation() {
timeline = new Timeline();
createTimelineContent();
timeline.setOnFinished(ActionEvent -> {
createTimelineContent();
timeline.play();
});
timeline.play();
}
private void createTimelineContent() {
timeline.getKeyFrames().clear();
duration = getRandomDuration();
KeyFrame kf1 =
new KeyFrame(Duration.ZERO,
new KeyValue( externalColor, oldExternalColor ),
new KeyValue( internalColor, oldInternalColor ));
oldExternalColor = getRandomColor(AnimatedGradients.baseExternalColor, AnimatedGradients.externalDelta);
oldInternalColor = getRandomColor(AnimatedGradients.baseInternalColor, AnimatedGradients.internalDelta);
KeyFrame kf2 =
new KeyFrame(new Duration(duration),
new KeyValue( externalColor, oldExternalColor ),
new KeyValue( internalColor, oldInternalColor ));
timeline.getKeyFrames().addAll( kf1, kf2 );
}
private void setBackground() {
bg = new Background(
new BackgroundFill(
new LinearGradient(0, 0, 0, 1, true, CycleMethod.NO_CYCLE,
new Stop[] { new Stop(0, externalColor.get()), new Stop(0.5, internalColor.get()), new Stop(1, externalColor.get())}
),
new CornerRadii(0),
new Insets(0, 0, 0, 0)
)
);
this.setBackground(bg);
}
private Color getRandomColor(Color color, double delta) {
int index = (int)( (color.getRed()+getRandomCoefficient(delta))*255 );
int r = ( index > 255 ) ? 255 : ( (index < 0) ? 0 : index );
index = (int)( (color.getGreen()+getRandomCoefficient(delta))*255 );
int g = ( index > 255 ) ? 255 : ( (index < 0) ? 0 : index );
index = (int)( (color.getBlue()+getRandomCoefficient(delta))*255 );
int b = ( index > 255 ) ? 255 : ( (index < 0) ? 0 : index );
return Color.rgb(r, g, b);
}
private double getRandomCoefficient(double delta) {
return ( rand.nextDouble()*2 - 1 ) * delta;
}
private int getRandomDuration() {
return (int)(( rand.nextDouble()*2 - 1 ) * AnimatedGradients.durationDelta * AnimatedGradients.baseDuration) + AnimatedGradients.baseDuration;
}}
2. This is example of animated Icon
public class AnimatedIcon extends WritableImage {
private ObjectProperty<Color> topColor = new SimpleObjectProperty();
private ObjectProperty<Color> bottomColor = new SimpleObjectProperty();
private Color oldTopColor;
private Color oldBottomColor;
private Timeline timeline;
private static final int DURATION = 5000;
private static final Random rand = new Random();
private static final int ICON_WIDTH = 32;
private static final int ICON_HEIGHT = 32;
private Stage primaryStage;
public AnimatedIcon(Stage primaryStage) {
super(ICON_WIDTH, ICON_HEIGHT);
this.primaryStage = primaryStage;
oldTopColor = Color.rgb(0, 45, 0);
oldBottomColor = Color.rgb(12, 128, 12);
topColor.set(oldTopColor);
bottomColor.set(oldBottomColor);
createGraphics();
bottomColor.addListener((obs, oldColor, newColor) -> {
createGraphics();
});
}
private void createGraphics() {
PixelWriter pixelWriter = this.getPixelWriter();
for (int y = 0; y < ICON_HEIGHT; y++) {
for (int x = 0; x < ICON_WIDTH; x++) {
double position = (double)x/(double)ICON_WIDTH;
int r = (int)( ( topColor.get().getRed() - (topColor.get().getRed() - bottomColor.get().getRed())*position ) * 255 );
int g = (int)( ( topColor.get().getGreen() - (topColor.get().getGreen() - bottomColor.get().getGreen())*position ) * 255 );
int b = (int)( ( topColor.get().getBlue() - (topColor.get().getBlue() - bottomColor.get().getBlue())*position ) * 255 );
double o = topColor.get().getOpacity() - (topColor.get().getOpacity() - bottomColor.get().getOpacity())*position;
pixelWriter.setColor(x,y,Color.rgb(r,g,b,o));
}
}
int index = primaryStage.getIcons().indexOf(this);
if (index == 0) {
primaryStage.getIcons().set(index, this);
} else {
primaryStage.getIcons().add(this);
}
}
public void startAnimation() {
timeline = new Timeline();
createTimelineContent();
timeline.setOnFinished(ActionEvent -> {
createTimelineContent();
timeline.play();
});
timeline.play();
}
private void createTimelineContent() {
timeline.getKeyFrames().clear();
KeyFrame kf1 =
new KeyFrame(Duration.ZERO,
new KeyValue( topColor, oldTopColor ),
new KeyValue( bottomColor, oldBottomColor ));
oldTopColor = Color.rgb(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256), rand.nextDouble());
oldBottomColor = Color.rgb(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256), 1);
KeyFrame kf2 =
new KeyFrame(new Duration(DURATION),
new KeyValue( topColor, oldTopColor ),
new KeyValue( bottomColor, oldBottomColor ));
timeline.getKeyFrames().addAll( kf1, kf2 );
}}
This is the main class for elements located above
public class AnimatedGradients extends Application {
protected static int baseDuration = 10000;
protected static Color baseExternalColor = Color.rgb(0, 0, 0);
protected static Color baseInternalColor = Color.rgb(127, 127, 127);
protected static double durationDelta = 0.25;
protected static double externalDelta = 0.1;
protected static double internalDelta = 1;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
HBox root = new HBox();
root.setSpacing(1);
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 761, 500, Color.BLACK);
primaryStage.setScene(scene);
AnimatedIcon ai = new AnimatedIcon(primaryStage);
primaryStage.getIcons().add(ai);
ai.startAnimation();
primaryStage.setTitle("Animated Gradients");
for (int i = 0; i < 10; i++) {
FilledRegion gr = new FilledRegion();
root.getChildren().add(gr);
gr.startAnimation();
}
primaryStage.show();
}}

Categories

Resources