Display the modified image of an ImageView object - java

I've been using an ImageView object to try and modify an Image and then draw it. However I could only make the two following outcomes happen:
1) After ImageView has been modified, I tried to grab the image out of it for display with getImage() but that only displayed the original Image I had in the first place.
example code:
sheet = new Image("file:sprite_sheet.png");
ImageView iv = new ImageView();
iv.setImage(sheet);
iv.setViewport(new Rectangle2D(0, 0, 32, 32));
g.drawImage(iv.getImage(), 100, 100);//'g' is GraphicsContext2D
2) I managed to get the modified image to show by adding it to the Group obj like so:
root.getChildren().add(iv);
But then it only displayed the image in the top left corner of the screen and I couldn't move it or do anything with it.
I prefer (if possible) to approach this issue with a method more like the first outcome has presented. And just saying this in advance, I'm aware of that that there's another post similar to this atm, but I couldn't get anything useful out of it.

ImageView, as the name implies, is just a view of the data (image in this case). All modifications to the view only affect the view and not the data. There are two general methods for what you want to achieve.
Use scene graph and ImageView object. Perform all visual operations on the view. This is the preferred way as the data stays the same, meaning you can easily create a new ImageView with the original image and modify it in a different way should you wish to. If the parent is Pane, then you can easily move the object by calling setTranslateX/Y.
If you absolutely need to use Canvas, then you will need to modify the data itself or create a copy of the data and modify it instead. You can do this by using a combination of the following: PixelWriter and PixelReader
Example for 1.:
ImageView view = new ImageView(image);
// create root with dimension 800x600
Pane root = new Pane();
root.setPrefSize(800, 600);
// attach view to root so it can be displayed
root.getChildren().add(view);
// translate view to 100, 100
// on the screen this means the image will move 100 in X and 100 in Y
view.setTranslateX(100);
view.setTranslateY(100);

Related

Field of view (FOV) of the Camera in the SceneView - ArcGIS Java runtime SDK

I'm trying to set the 3D Camera of the SceneView in the Java SDK and I cannot find a "field of view" / "angle of view" member.
I was wondering how the camera's field of view is being set, since I need a way to change it according to the horizontal and vertical field of views.
Code snippet:
// set title, size, and add JavaFX scene to stage
...
// create a scene and add a basemap to it
scene = new ArcGISScene();
scene.setBasemap(Basemap.createImagery());
// add the SceneView to the stack pane
sceneView = new SceneView();
sceneView.setArcGISScene(scene);
sceneView.setMinSize(WIDTH, HEIGHT); // WIDTH = 480, HEIGHT = 270
sceneView.setMaxSize(WIDTH, HEIGHT);
Camera camera = new Camera(lat, lon, alt, yaw, pitch, roll); // Defined above...
sceneView.setViewpointCamera(camera);
What I want is the ability to control how much is visibile on the rendered map (i.e., control the vertical and horizontal field of view of the Camera).
I've gone through every member and method of SceneView, Scene and Camera but couldn't find anything.
The current situation is the map is rendered with the given width and height but ESRI/ArcGIS must use a field of view somewhere to determine what or how much is visible.
The same field exists on the JavaScript API ('fov' memeber of the Camera class). I've done research on that field and came to a conclusion it's probably the horizontal field of view, but it's still unclear to me.
Anyway, I need the same field for the Java runtime SDK.
I would really appreciate your help!

Shrinking JavaFX Graphics

I'm looking for a way of rendering a scene hidden from view and then creating a second shrunken copy for initial display. Plainly I could render the contents a second time to create this copy only smaller. The original code written in another language though produced a better result using a smooth (spatially filtered) shrinking function to create the small copy. Is there such a bitmap copy/shrink/smooth function in JavaFX and is it any good?
You can create a snapshot of a scene as a WritableImage as follows:
Scene scene = ... ;
Image image = scene.snapshot(null);
and then display a scaled version of it in an image view with:
ImageView sceneImage = new ImageView();
sceneImage.setFitWidth(desiredWidth);
sceneImage.setFitHeight(desiredHeight);
// force aspect ratio to be preserved if fitWidth and fitHeight would distort it:
sceneImage.setPreserveRatio(true);
// this provides a tiny bit of control over the scaling used:
sceneImage.setSmooth(true);
sceneImage.setImage(image);

How to define a clickable area in an image used in ImageView

Is there a way to define a clickable area in an image? Something equivalent or similar to map-area tags in HTML? Or is there a standard way of doing this sort of thing?
A possible method
1) get the width, and height of the image view using (in pixels)
2) get the coordinates of the image view (which is the top left corner of the image view)
3) create a touch listener, and record the coordinates of the users touch
4) if the user's touch coordinates fall on the image do whatever you want to
If you only want to do certain things based on where the user touches you will have to calculate the coordinates of those regions using the coordinates of the image view, and the image views width and height.
I think there might be no standard way for this, but you can achieve it by placing a transparent VIEW over your imageview. Set click listener to that view and make imageview clickable false.
When i have to do something similar, i use an include view.
As for the layout the include view will be accessing, i would use FrameLayout as root.
Its children would be the ImageView that i want to depict, along with a LinearLayout infront of it containing Buttons at the positions i want the user to choose from.
Then in code, i set listeners to these buttons.
Lastly, i would set the buttons so that there background is transparent and text is not available.
For example in a project i am working on, i have an ImageView with an Image of Ocean as background.
In front of the view i have a LinearLayout with smaller ImageViews with images of islands.
I place listener on the islands to see when they are clicked to open a new activity.

How do I create a view following the player in a JavaFX game?

I'm trying to make my first game in JavaFX, where a player object (not a Node) will move inside a level. However, the full level shouldn't be visible inside the window, only a part of it surrounding the player should be. I've searched quite a bit for a solution to this that works with the way I've done my project, but haven't been successful. The following code describes how I've set up my GUI:
private VBox appRoot;
private Pane gameRoot;
private Canvas canvas;
private GraphicsContext gc;
private HBox uiRoot;
This is the different panes I use. The appRoot contains both the gameRoot and the uiRoot, in that order. The gameRoot contains the canvas. Everything inside the level, including the level itself, is drawn onto the canvas, like this:
canvas = new Canvas(ROOM_WIDTH, ROOM_HEIGHT);
gc = canvas.getGraphicsContext2D();
createLevel(ROOM_WIDTH, ROOM_HEIGHT, CELL_WIDTH, CELL_HEIGHT);
gc.scale(2, 2);
drawLevel(gc, ROOM_WIDTH, ROOM_HEIGHT, CELL_WIDTH, CELL_HEIGHT);
player.render(gc);
createLevel and drawLevel just creates a level and draws squares where different blocks should be. The player object's render method draws the player at its x- and y-coordinates. As you can see I've scaled the canvas, so as of now the entire level isn't shown when the game is started.
The problem is that I can't make it so that what is shown in the window is the things surrounding the player object. I've seen some code utilizing the methods setLayoutX and setLayoutY, but I've been unable to reproduce this so that it works.
I would be very grateful if anybody could help me out with this, and hopefully without changing too much of how the drawing is done.
Thanks! :)
Also, here are two pictures showing how it looks; the first is when the player is not inside the current view, and the second is with the player in the view.
Image without player in view
Image with player in view
Do not us the Canvas directly to display the level. Instead you can use an image that represents your level and then have the image in an ImageView. On that ImageView you can define a viewport of the area of the image that is visible.
To get the image you can either use your Canvas node and take a snapshot (See this question). This is probably the easiest way with what you have. Or you can forego the Canvas altogether and draw the image. If the levels are predefined (and not generated at runtime), this seems the best approach, then you can supply the images as resources along with the code.

Libgdx: overlaying two images into scene 2D table

I'm trying to make a progress bar in LibGdx. I'm using scene 2D to put elements into the screen (is a loading screen). I'm using a table, where I put an image, a label ("loading...") and a progress bar.
The progress bar is composed by two images. My problem is that I cannot overlay the two images. I'm using this code
stage.addActor(root);
root.add(image).width(200).height(200);
root.row();
root.add(new Label("Loading...", skin));
root.row();
root.add(progressBarBG).width(600);
root.add(progressBarFG).height(30).width(30);
root.pack();
Gdx.input.setInputProcessor(stage);
But the progressBarBG and progressBarFG are draw one followed by the other. It is a way to put one over the other one?
ProgressBarBG and ProgressBarFG are loaded from a texture atlas. Root is a Table.
Thanks.
As Springrbua mentioned, it's best to use ProgressBar for this.
Though, to answer your question, you can use a Group to overlap images with scene2d. Simply add all of the images to one group, then add that group to the desired parent. If you need to offset any of the images in the group, you can use image.setPosition(offsetX, offsetY). Here's an example for your case:
stage.addActor(root);
root.add(image).width(200).height(200);
root.row();
root.add(new Label("Loading...", skin));
root.row();
//Use groups to overlay multiple images
Group group = new Group();
progressBarBG.setWidth(600);
progressBarFG.setSize(30, 30);
group.addActor(progressBarBG);
group.addActor(progressBarFG);
root.add(group);
root.pack();
Gdx.input.setInputProcessor(stage);
I used this code to place a diamond image over a box image:
Image boxImage = new Image(Assets.instance.gifts.box);
Image diamondImage = new Image(Assets.instance.gifts.diamond);
Stack diamondBox = new Stack();
diamondBox.addActor(boxImage);
diamondBox.addActor(diamondImage);
tbl.add(diamondBox).width(20).height(20);
tbl.row();

Categories

Resources