GridPane inside AnchorPane - javafx-8

I put a Gridpane inside on the AnchorPane , my Gridpane has a set of TextField , Label and Buttons and I want it to put in the Anchorpane but my GridPane is just sticking in the upper left of the AnchorPane i've set a setTopanchor etc... for the GridPane but it don't apply to the Anchorpane i want it to put in the center. here is the sample . Is there any missing for it just don't really apply in AnchorPane? tnx I'll be waiting for your help.

If i got your question right and you want to center GridPane in AnchorPane, you can try something like this on each AnchorPane width or height changes (anchorPane.widthProperty().addListener()):
double x = (anchorPane.getWidth() - GRID_SIZE) / 2;
double y = (anchorPane.getHeight() - GRID_SIZE) / 2;
AnchorPane.setRightAnchor(grid, x);
AnchorPane.setTopAnchor(grid, y);
AnchorPane.setLeftAnchor(grid, x);
AnchorPane.setBottomAnchor(grid, y);
Basically, you need to calculate offset from each side and set an anchor.
Here is some demo code for StackPane and AncorPane:
https://github.com/varren/JavaFX-Center-GridPane-in-other-Pane/tree/master/src/sample
But if you just want your grid to take full AnchorPane size, you can simply set
AnchorPane.setRightAnchor(grid, .0);
AnchorPane.setTopAnchor(grid, .0);
AnchorPane.setLeftAnchor(grid, .0);
AnchorPane.setBottomAnchor(grid, .0);
And there will be no need to listen for AnchorPane size changes.

Related

Draw line relative to Image position and scale

I am making a game in Unity and I have a Canvas set to Screen Space - Overlay and it has that background green as you can see from the image. I also have a RawImage with the background blue as a child of the Canvas and the player will have to draw an object like a car or a house inside the RawImage.Right now, the line Instantiates in a random position on the screen even if I give it the coordinated (0, 0).
What I need help with is to find a way to convert the coordinates so I only work with the inside coordinates of the RawImage. For example, the (0, 0) coordinate I will pass to the line, has to be converted to the bottom-left corner of the RawImage. and the maximum width or height should also depend on the RawImage width and height.
Here is the CreateLine function I have for now:
public void CreateLine(int x, int y)
{
currentLine = Instantiate(linePrefab, Vector3.zero, Quaternion.identity);
currentLine.transform.parent = GameObject.Find("GameMenu(Clone)").transform; //Make the line a child of the Canvas named GameMenu
lineRenderer = currentLine.GetComponent<LineRenderer>();
lineRenderer.SetPosition(0, new Vector3(x, y, 99));
lineRenderer.SetPosition(1, new Vector3(x, y, 99));
}
Any amount of help will be greatly appreciated. Have a great day!

How to put vertical bar at the end of filled area of unity3d horizontal slider

I am using unity3d horizontal slider to show a character's life like below
But I want to show a vertical bar at the end of filled area like in below image
Any idea? how to achieve this.
You can do this by Lerping the localPosition of your vertical bar.
This would look something like the following:
GameObject verticalBar; //the gameobject you want to use
GameObject player; //Assume this is your play that has the health property
Vector3 startPos; //start position of your total healthbar
Vector3 endPos; //end position of your total healthbar
private void UpdateVerticalBarPosition()
{
float normalized = player.currentHealth / player. maxHealth //this normalizes your current health to be between 0 and 1
if(!float IsNaN(normalized))//(optional) makes sure the value is valid.
{
verticalBar.transform.localPosition = Vector3.Lerp(startPos, endPos, normalized);
}
}
This method will normalize your current HP. meaning that if for example your player has 70 health left of a total 100 health, the normalized value will be 0.7f, or 70% of its total health.
Using this normalized value in a Vector3.Lerp that is clamped between startPos and endPos (here startPos would be the starting position of your total healthbar, so the left side of your grey bar. And endPos the ending positon of your total health bar, so the right side of your grey bar) will put the vertical bar 70% along of the way of your health bar. Which should be the same point where your yellow/orange bar stops.
If you call this method once when hp has changed it will jump to the new value. But if you take damage gradually you can also run it in a loop to make it slide across smoothly.
Alternatively. If you use Unity's Slider component for your healthbar you can also just use the Slider.handleRect. found in the documentations here which would look something like this
Slider healthBar; //the slider used for your healthbar
GameObject verticalBar; // the bar you want displayed at the end of the healthbar
Start()
{
healthBar.handleRect = verticalBar;
}
I solved this, It was pretty simple though!
I just a added the vertical bar texture as child of fill image inside slider and I kept it right aligned.
cheers!

Unity: Instantiate GameObject at top of screen plus it's own height

I have this code that instantiates GameObjects at the top of the screen and then they fall down.
float RandX = GetRandomXPos();
float RandY = screenSize.y;
Vector3 ballPos = new Vector3(RandX,RandY,0);
GameObject clone = Instantiate(BallPrefab, ballPos, transform.rotation) as GameObject;
This works fine but it spawn them at the top of the screen so they just blink into existence. I want to spawn them at the top of the screen plus the height of the prefab so that it can appear out of view and then fall down into view.
What is the best way to get that height that I need to offset by?
To get the size of the prefab you need to get the information of the Renderer that the prefab has.
To do this you have to get the component in its hierarchy, you can do this by using GetComponentInChildren<Renderer>()
Once you got the Renderer, you can access the bounds size with renderer.bounds.size
This is a Vector3 which has the dimensions of the object, height being the Y component.
You may have more than one Renderer in a prefab so you will need to get them all with GetComponentsInChildren<Renderer>(). and calculate the sum of all the bounds using bounds.Encapsulate
var renderer = target.GetComponentInChildren<Renderer>();
var height = renderer.bounds.size.y;

JavaFX 8, how to get center location of Scrollpane's Viewport

The Problem
I'm trying to figure out a way to get at which point in the content node the scroll pane's viewport is centered on.
To elaborate on the picture above, the big rectangle is the content (let's say a large image), and the small rectangle is the portion that is shown by the scroll pane. I'm trying to find x and y which would be coordinates from the top left of the content.
What I've Tried
My first thought was to use the getViewportBounds() method of the scroll pane and use its minX and maxX properties to determine the center x point:
Bounds b = scrollPane.getViewportBounds();
double centerX = (b.getMinX() + b.getMaxX()) / 2;
double centerY = (b.getMinY() + b.getMaxY()) / 2;
However, this doesn't work because these numbers are negative and don't seem to accurately describe the x and y I'm looking for anyways.
My next thought was to use the scroll pane's hValue and vValue to get the top left corner of the viewport relative to the content:
Bounds b = scrollPane.getViewportBounds();
double centerX = scrollPane.getHvalue() + b.getWidth() / 2;
double centerY = scrollPane.getVvalue() + b.getHeight() / 2;
This didn't work either though as the hValue and vValue seem to be way too large (when scrolled in only a few pixels, I'm getting numbers like 1600).
My Questions
I seem to have a fundamental misunderstanding of how the viewport works with a scroll pane.
What am I doing wrong here? Can someone explain where these numbers come from? How do I find x and y like in the picture above?
Let (x, y) be the be coordinates of the top, left point shown in the viewport. You can write this as
((contentWidth - viewportWidth) * hValueRel, (contentHeight - viewportHeight) * vValueRel)
vValueRel = vValue / vMax
hValueRel = hValue / hMax
This means assuming hmin and vmin remain 0 you can keep a circle in the center of like this:
// update circle position to be centered in the viewport
private void update() {
Bounds viewportBounds = scrollPane.getViewportBounds();
Bounds contentBounds = content.getBoundsInLocal();
double hRel = scrollPane.getHvalue() / scrollPane.getHmax();
double vRel = scrollPane.getVvalue() / scrollPane.getVmax();
double x = Math.max(0, (contentBounds.getWidth() - viewportBounds.getWidth()) * hRel) + viewportBounds.getWidth() / 2;
double y = Math.max(0, (contentBounds.getHeight() - viewportBounds.getHeight()) * vRel) + viewportBounds.getHeight() / 2;
Point2D localCoordinates = content.parentToLocal(x, y);
circle.setCenterX(localCoordinates.getX());
circle.setCenterY(localCoordinates.getY());
}
private Circle circle;
private Pane content;
private ScrollPane scrollPane;
#Override
public void start(Stage primaryStage) {
// create ui
circle = new Circle(10);
content = new Pane(circle);
content.setPrefSize(4000, 4000);
scrollPane = new ScrollPane(content);
Scene scene = new Scene(scrollPane, 400, 400);
// add listener to properties that may change
InvalidationListener l = o -> update();
content.layoutBoundsProperty().addListener(l);
scrollPane.viewportBoundsProperty().addListener(l);
scrollPane.hvalueProperty().addListener(l);
scrollPane.vvalueProperty().addListener(l);
scrollPane.hmaxProperty().addListener(l);
scrollPane.vmaxProperty().addListener(l);
scrollPane.hminProperty().addListener(l);
scrollPane.vminProperty().addListener(l);
primaryStage.setScene(scene);
primaryStage.show();
}

How to get screen/scene center x,y of Rectangle within a GridPane?

I'm working on a simple board game implementation in JavaFX8.
For the game board, my decision was to use a 10x10 GridPane and fill it's cells with Rectangles in form's initialize method.
private void drawBoard() {
gridpaneBoard.getChildren().clear();
for (int y = 0; y < gridpaneBoard.getRowConstraints().size(); y++)
for (int x = 0; x < gridpaneBoard.getColumnConstraints().size(); x++) {
Rectangle rect = new Rectangle(55,55);
rect.setStroke(Color.BLACK);
Tile tile = GameController.getInstance().getBoard().getTile(x, y);
if (tile.hasBranch())
rect.setFill(QuestionDifficulty.values()[tile.getBranch()
.getQuestion().getQuestion()
.getLevel()].getColor());
else
rect.setFill(Color.WHITE);
gridpaneBoard.add(rect, x, y);
gridpaneBoard.add(new Label(String.valueOf(tile.getNumber())), x, y);
}
}
In order to animate player token movement after dice rolls, I figured I need to know the center x & center y of each tile (to create a path transition from source tile to destination tile).
I've tried all sorts of answers given to other people's questions, but everything returned 0,0 for me.
This is the container hierarchy in this scene:
This is how the output looks at the moment:
If GridPane is fine for what I'm trying to achieve, how can I get a child's (in this case a rectangle's) screen / scene center x,y?
If GridPane is not fine, can you point me to alternatives and how I can achieve what I want then..
Thank you!
You can simply call getBoundsInParent to get the dimensions of the Node in it's parent.
The following example is a bit simplified, but it should demonstrate the approach nonetheless:
#Override
public void start(Stage primaryStage) {
GridPane gridpaneBoard = new GridPane();
for (int y = 0; y < 10; y++) {
for (int x = 0; x < 10; x++) {
Rectangle rect = new Rectangle(55, 55);
rect.setStroke(Color.BLACK);
rect.setFill((x + y) % 2 == 0 ? Color.WHITE : Color.DARKGRAY);
gridpaneBoard.add(rect, x, y);
}
}
gridpaneBoard.setOnMouseClicked(evt -> {
Node target = evt.getPickResult().getIntersectedNode();
if (target != gridpaneBoard) {
// in your case you'd need to make sure this is not the Label
Bounds bounds = target.getBoundsInParent();
System.out.println("bounds = " +bounds);
System.out.println("centerX = " +(bounds.getMinX() + bounds.getWidth()/2));
System.out.println("centerY = " +(bounds.getMinY() + bounds.getHeight()/2));
}
});
Scene scene = new Scene(gridpaneBoard);
primaryStage.setScene(scene);
primaryStage.show();
}
If coordinates different to the GridPane coordinates are required, you could use getBoundsInLocal in combination with localTo... instead:
Bounds bounds = target.localToScene(target.getBoundsInLocal());
for scene bounds or
Bounds bounds = target.localToScreen(target.getBoundsInLocal());
for screen bounds.
Note: This works independent from any properties modifying how GridPane layouts it's children.
You can use :
-GridPane.getColumnIndex(Node) to get the column index.
-GridPane.getRowIndex(Node) to get the row index.
-Since you know the Width and the Height (55,55) of your child (Rectangle) you can just calculate its centerX, centerY which is relative to its position in the container, but since you use a GridPane I don't think it is possible since this one has Constraints. You can fix it by changing the container of your object or completely redraw it inside another raw/column, here is an example Replace a node at (row,col).