Change position of text inside AnchorPane? - java

Hello I have got the following code where I am adding a circle inside my anchorpane, and onto the circle I am adding a text.
Circle is an Circle, ArrayList, with multiple circles.
pane.getChildren().addAll(circle);
pane.getChildren().addAll(circle.stream().map(circ -> {
Label text = new Label(circ.getId());
text.setAlignment(Pos.CENTER);
AnchorPane.setLeftAnchor(text, circ.getCenterX());
AnchorPane.setTopAnchor(text, circ.getCenterY());
return text;
}).toArray(Label[]::new));
}
I can change the position from my circle with circle.get(i).setCenterY();
But how can I change the position of the text I added onto the circle?
Thank you in advance

To access the labels, you need to keep a reference to them, e.g.
pane.getChildren().addAll(circle);
List<Label> labels = circle.stream().map(circ -> {
Label text = new Label(circ.getId());
text.setAlignment(Pos.CENTER);
AnchorPane.setLeftAnchor(text, circ.getCenterX());
AnchorPane.setTopAnchor(text, circ.getCenterY());
return text;
}).collect(Collectors.toList());
pane.getChildren().addAll(labels);
And now of course you can just do
AnchorPane.setLeftAnchor(labels.get(i), newXValue);
AnchorPane.setTopAnchor(labels.get(i), newYValue);

Related

GUI - Chess game drag pieces and drop into a board " 2D array "

Hello I'm trying to make a chess game, so far I have created my pieces and I can move them with my mouse.
Now I'm trying to make the board with a 2D array that contains chess piece, so that I when I drag a piece on the board, it adds the piece in the array for example on the image
I drag the piece to (2,3) and board[2][3] = pawn
But I'm not sure how to implement it, I thought about using coordinates like when I drag it into the middle, say I have a frame size of 800x800 and board size of 8 so when I drag my piece to the coordinate (400,400), board[4][4] = pawn, but then I have to do it for each cell and I'm gonna end up with up 64 if conditions, is there some kind of trick to do it or is my approach wrong?
If( piece's position is between ... and ... ){
then put into board[0][1]}
If ( piece's position is between ... ) {
then put then put into board[1][1]}
You could use a mouseListener on the JLabels you have in your board! First, build your board by using 8*8 (chess is 8*8, right?) JLabels, store them in some array.
JLabel[][] boardFields = new JLabel[8][8];
You pack these in a JPanel which has GridBagLayout. You can lay them out in the desired pattern pretty easily by using the GridBagContraints class'vgridx and gridy variables.
Now what you do is make a static variable somewhere, lets call it selectedPiece. Lets add the mouse listeners to all of our field labels:
for(int i=0;i<8;i++){
for(int j=0;j<8;j++){
boardFields[i][j] = new JLabel();
//set its background white or black here
//each field will listen to a mouse press (means we selected this piece)
//and a mouse release (meaning we placed the selected piece here)
boardFields[i][j].addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
selectedPiece = //set piece on this field somehow
//update the background to plain black or white
//make the icon of the piece follow the cursor
}
public void mousePressed(MouseEvent e){
//update the background to contain the selectedPiece
//make the icon of the piece stop followin the cursor
selectedPiece = null //de-select the piece since we just placed it
}
)};
}
}
This is just a sketch obviously, but it should give you the idea!

Getting the absolute coordinates of a node in a BorderPane with some null regions

I have a set of custom made "buttons" for the menu screen of my game. It's basically a StackPane with a Rectangle and a Text node stacked. Basically this is similar to how my buttons are structured.
Pane button1 = new StackPane(new Rectangle(100, 50), new Text("Play!"));
Pane button2 = [....];
Then I insert buttons into a VBox and into my menu along with a header text:
VBox buttons = new VBox(button1, button2, button3...);
Pane menuScreen = new BorderPane(buttons, new Text("The Game"), null, null, null);
However, for my custom detection for mouse position compared to the buttons I need to know the buttons' positions...
int x = button1.getLayoutX(); //returns 0
int x = button1.getTranslateX(); //returns 0
int x = button1.localToScene(0, 0).getX(); //returns 0
int x = button1.localToScene(buttons.get(0).getBoundsInLocal()).getMinX(); //returns 0
int x = button1.localToScene(buttons.get(0).getBoundsInLocal()).getMaxX(); //returns the width of the entire scene
int x = buttons.get(0).getTranslateX(); //returns 0
int y = button1.localToScene(buttons.get(0).getBoundsInLocal()).getMinY();
The last case returns 234.0 if I have the VBox set with .setAlignment(Pos.CENTER) and 64.0 if I don't. But for .getMinX() it stays at 0.0 in either case. I believe it's related to the BorderPane's left/right/bot regions being set to null while the top region has the title text.
I cannot find any way of getting the x coordinate when the buttons are in a layout pane other than the Pane class itself. I tried StackPane as well. My suspicion is that there is no fixed coordinate and that properties are involved, but I only get confused from reading about it when I don't know what I'm looking for.
I have tried solutions from this quesion and this seems to be the same but as I mentioned I'm afraid my minX() doesn't have a set value since the VBox is the only thing filling the center row of my BorderPane.
Edit: StackPane seems to give the right values for .getMinX() when I use .setAlignment(Pos.CENTER), but I am not allowed to do that with the text, only with the VBox, so then the text gets stuck on top of the buttons.
My issue was cause by the VBox and my StackPanes taking up all the possible space, not just the area of the visible Rectangle. Problem was solved by calling setMaxWidth(100) on the StackPane which contained the Rectangle and the Text.
Also, the only problem seems to be that you have a zero x-coordinate. Maybe this is "real". Set a background on button1 to see where it is in the layout. – James_D

Grouping objects in JavaFX?

So I'm currently making a JavaFX GUI (with SceneBuilder) for a Connect4 game, and I was wondering if there's a way to 'group' objects together so that I can perform an action on all of them together?
Examples of what I mean:
I have 7 buttons for the columns (colButton1-7) and I want to disable all of them at once.
I use Ellipses for counters (counter1-40) and would like to change the color of all of them to white.
I searched around but couldn't find anything. I know how to do both for an individual object, but can't think of a way to easily apply the changes to all of them at the same time. Any help would be appreciated :)
There is no grouping mechanism to perform a single action on all of the members of the same group. On the contrary, you can have a single group/container to hold all your controls and apply the same action to each of its member.
For example, lets say I have a VBox containing Buttons and I want to disable them all.
for(Node node:vBox.getChildren()) {
node.setDisable(true);
}
or, to set Styling
for(Node node:vBox.getChildren()) {
node.setStyle("-fx-something");
}
For disabling, if you disable a node, then all it's child nodes will have disabled set to true. So you can do:
VBox buttonHolder = new VBox();
Button button = new Button(...);
buttonHolder.getChildren().add(button);
// repeat as necessary...
buttonHolder.setDisable(true); // all buttons in the VBox will now be disbaled
For styled properties, such as the fill of a shape, you should use an external style sheet. If you change the style class of the parent, then with an appropriate external style sheet you can change the style of all the children in one shot.
E.g.
Pane counterPane = new Pane();
for (int i=0; i<numCounters; i++) {
Ellipse counter = new Ellipse(...);
counter.getStyleClass().add("counter");
counterPane.getChildren().add(counter);
}
// ...
counterPane.getStyleClass().add("counter-pane"); // all counters white
// change to red:
counterPane.getStyleClass().remove("counter-pane");
counterPane.getStyleClass().add("warning");
External style sheet:
.counter-pane > .counter {
-fx-fill: white ;
}
.warning > .counter {
-fx-fill : red ;
}

How to avoid that multiline text is clipped in javafx?

I have a GridPane which I'm filling with various graphical/textual elements.
For the text, single line labels gets the right size. The same happens to e.g. images
of various sizes (the grid is stretched to give space for the image).
However, for multiline text elements (a.e. a label containing text with newlines in it), it clips the element at one line height... How can I force an UI element (like a label) to take up enough space to display its content?
Here's some code (scala):
val chatPanel = new GridPane {
setFitToWidth(true)
setFitToHeight(true)
setManaged(true)
setMaxWidth(10000)
setMaxHeight(10000)
}
def sendTextInfoBlock(title:String,message:String) {
val button = new Label(message) {
// setWrapText(true)
// setMinHeight(100) <- this works, but of course doesn't match the required height
}
// val button = new Button(message)
chatPanel.add(button,1,row)
the message is a text with newlines, like "this is a long\nand interresting\nmessage"
I gave up, stacked a VBox full of labels (one label per line of text), and just styled it
like a button. That worked well at least.

How can I have my top level Jpanel set its location relative to a jlabel that is in another jpanel's grid?

The scenario: I have a UI that contains a JPanel (call it topGrid) with a grid layout in a JFrame at the top level. Within topGrid, I have placed another JPanel (midGrid) with grid layout. Inside midGrid, is another JPanel (bottomGrid) that has a JLabel that I populate with images depending on an array and what their instance is within that array.
The goal: I would like the topGrid to center its view on a specific object found in bottomGrid. (Picture a game that as the player icon moves, the game's grid moves to center on that icon and also when the game is started it is already centered for the user.)
I've considered getting the Point from bottomGrid and trying to pass it over to topGrid but doesn't seem to pull the correct information. The only way i know to find where the player is, is to iterate through all the components and check instances. this would have to be done once for the topGrid and again for midGrid to find the player at bottomGrid. then pass the Point data. Then use setLocation() on the appropriate JPanel minus the distance from the center.
Has anyone else tried this and have a more effective or elegant way to go about it? What other options could I explore?
Thanks for any feedback.
Creating the grid within topGrid's JPanel:
public void createTopGrid()
{
int rows = galaxy.getNumRows();
int columns = galaxy.getNumColumns();
pnlGrid.removeAll();
pnlGrid.setLayout(new GridLayout(rows, columns));
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < columns; col++)
{
Position pos = new Position(galaxy, row, col);
Sector sector = galaxy.getSector(pos);
GalaxySector sectorUI = new GalaxySector(sector);
pnlGrid.add(sectorUI);
}
}
}
Creating the grid within midGrid's JPanel:
public void createOccupantIcons()
{
pnlGridOccupants.removeAll();
Occupant[] occs = sector.getOccupantsAsArray();
for ( Occupant occ : occs )
{
GalaxyOccupant occupant = new GalaxyOccupant(occ, sector);
pnlGridOccupants.add(occupant);
}
}
The Image icons for each occupant in the midGrid are pulled from an IconRep String in the model in the bottomGrid class' JPanel and added into a JLabel as needed in FlowLayout.
For visual reference:
Where green square is topGrid JPanel, red squares are midGrid JPanel, and the black square is the bottomGrid JPanel with the white circle for the player image inside a JLabel. The blue circle represents a viewport the user will see the game through and is where I want the player icon to be centered to. Currently the user can move the grid's using very inelegant buttons in the area around the viewport. That might be sufficient but at the start of the game the player has to move the grid around until they can locate their icon.
You might also look at JScrollNavigator, examined here. It would allow you to navigate on a thumbnail image of your entire world, seen at full size in an adjacent scroll pane.
Off the top of my head, I would store all the references you want to in some kind of model.
You could use this model to update the views based on selection requirements.
This allows the you to centralise the logic for finding and updating the elements without knowing or caring out the other UI elements

Categories