JavaFX positioning of a button - java

How do I set the position of a Button in JavaFX? My Code:
bZero = new Button();
bZero.setPrefSize(45, 20);
mainPane.getChildren().add(bZero);

If you use a container that does not manage layout, such as a plain Pane, then you can use
bZero.setLayoutX(...);
bZero.setLayoutY(...);
or, equivalently,
bZero.relocate(...);
However, as suggested in the comments, it is far preferable to use a pane that manages the layout for you.

You can use setX and setY properties of the button to position it in a Pane
bZero = new Button();
bZero.setPrefSize(45, 20);
mainPane.getChildren().add(bZero);
bZero.setLayoutX(100); // Sets the X co-ordinate
bZero.setLayoutY(200); // Sets the Y co-ordinate

Related

Adding JButtons in for loop

JAVA Swing Problem
I want to create a list of JButtons based on a list of strings, which represents the button text.
In my first step, I collect my data for the button texts from an external text file. This data is stored in the data variable.
List<String> data = ReadFile("texts.txt")
Now I want to create the list of JButtons, named buttons. There I set their text and their Bounds. The Bounds are relative to the index, so the buttons are placed below each other. Finally, I add the button to the frame and to the buttons list.
List<JButton> buttons = new ArrayList<>();
for (int index = 0; index < data.size(); index++) {
JButton button = new JButton();
button.setText(data.get(index));
button.setBounds(0, index*50, 100, 50);
add(button);
buttons.add(button);
But when I execute this, the last Button ends big, the first ones also disappear when I don't hover over them, but that's based on the fact, that the last button ist placed above:
Picture of the executed script
The last button has the size of the frame, doesn't matter, if I resize the frame:
Picture of the resized screen
I hope someone can help me or tell me where I can find help. Thanks.
the last Button ends big, the first ones also disappear when I don't hover over them,
That is because by default the content pane of the JFrame uses a BorderLayout. When you add a component to the BorderLayout the button is added to the CENTER. However, only a single component can be added to the CENTER, so only the size/location of the last component added is managed by the BorderLayout.
Don't attempt to set the size/location of your components manually. It is the job of a layout manager to do this. In your case you can use a couple of panels with different layout so align your button in a column on the left. Something like:
JPanel buttonPanel = new JPanel( new GridLayout(0, 1) );
for (int index = 0; index < data.size(); index++) {
JButton button = new JButton();
button.setText(data.get(index));
button.setBounds(0, index*50, 100, 50);
//add(button);
buttonPanel.add( button );
buttons.add(button);
}
add(buttonPanel, BorderLayout.LINE_START);
Try the above code and you will notice that the buttons are all the same size, but the size keeps changing as the height of the frame changes.
So to prevent this resizing we need to allow the button to be displayed at their preferred height by using an additional layout manager:
//add(buttonPanel, BorderLayout.LINE_START);
JPanel wrapper = new JPanel( new BorderLayout() );
wrapper.add(buttonPanel, BorderLayout.PAGE_START);
add(wrapper, BorderLayout.LINE_START);
Read the Swing tutorial on Layout Manager for more information and examples.

setX and setY not working when trying to position images

I am having problems with positioning my images in my JavaFX program using setX and setY on the ImageView's for the images. I am not sure what is the problem? Appreciate any help given!
Here's my code:
Image rocket2 = new Image("img/Rocket.png");
ImageView iv1 = new ImageView(rocket2);
iv1.setX(60);
iv1.setY(44);
Image rocket1 = new Image("img/Rocket.png");
ImageView iv2 = new ImageView(rocket1);
iv2.setX(5);
iv2.setY(16);
Image background = new Image("img/space.png");
ImageView iv3 = new ImageView(background);
StackPane root = new StackPane();
root.getChildren().addAll(iv3, iv2, iv1);
Scene scene = new Scene(root, 300, 300);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.setTitle("Space stuff");
primaryStage.show();
I suspect that something goes wrong because I have set a background image.
img here on what's happening
Don't place your items in a StackPane if you want to explicitly define their layout positions (setX and setY). A StackPane is a managed layout pane. It will automatically set the location of items added to it (default is to center everything one on top of the other inside the StackPane).
Instead use a Pane or a Group, which are not managed layout panes and allow you to layout your content in the Pane however you wish.
To layout your content inside the Pane, you can use setLayoutX and setLayoutY rather than setX and setY, though I guess setX and setY should also work (I've never used them before on ImageView).
Pavlo, already created an answer while I was typing this (so this answer is a duplicate), but I'll leave this as it adds a bit more explanation.
Replacing StackPane with Pane should solve the problem.
If you however want for whatever reason to position a item in a StackPane you can use setTranslateX and setTranslateY. Theese methods set the x and y values AFTER the StackPane has done its layouting, so you will have a different starting position depending on the Alignment your StackPane uses for its children.

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

JavaFX Button with multiple text lines

I need to create a toolbar in my screen that will have multiple buttons, and each button must have multiple lines of Text. For example:
I looked over the internet and StackOverflow but I couldn't find anything showing how to do this in JavaFX. I'm using JavaFX 8.
Someone could help me, please?
Tks
Also you can use the wrapTextProperty. But you have to set toolbar height greater than expected button height.
Button btn = new Button();
btn.wrapTextProperty().setValue(true);
// or btn.setWrapText(true);
btn.setText("Some looooooooooooong text");
Or if you want to determine exactly where the line should be wrapped, you can go this way:
Button btn = new Button();
btn.setText("Line1\n Line2\n Line3");
Last way will work without changing toolbar height.
I resolved this problem including a VBox inside my button, and then including several Labels inside the VBox. Like this:
The result is:
If there is a more elegant way to have the same result, please, let me know.
Thank you.
In the button text property select "switch to multi-line mode
"
From sobolev's response, you can do:
Button btn = new Button();
btn.setText("Line1\n Line2\n Line3");
button.textAlignmentProperty().set(TextAlignment.CENTER);
This will create 3 lines of text and allign them in the center of your button.
My solution is pretty much the same as the one given by the OP, but instead of Label uses Text so it's more flexible to changes in the size of the button, as it will use as many lines as needed. If required, also one can set a wrapping width, to define a width constraint.
#Override
public void start(Stage primaryStage) {
Button btn = new Button();
ImageView imageView = new ImageView(new Image(getClass().getResource(<image>).toExternalForm()));
Text text=new Text("Some long text that may be line wrapped");
text.setWrappingWidth(100);
VBox vBox = new VBox(5, imageView,text);
vBox.setAlignment(Pos.CENTER);
btn.setGraphic(vBox);
btn.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
Scene scene = new Scene(new StackPane(btn), 300, 250);
primaryStage.setScene(scene);
primaryStage.show();
}
Label label= new Label("your long text here");
label.setStyle("-fx-max-width : 180px);
label.setWrapText(true);

Buttons in a horizontal panel don't want to align right

I have a horizontal panel with 3 buttons: Back, Next and Cancel. I've made horizontal alignment to the right, but only Next and Cancel buttons follow this alignment.
Here is the code:
HorizontalPanel buttons = new HorizontalPanel();
buttons.setWidth("100%");
cancel = new Button("Cancel");
next = new Button("Next");
back = new Button("Back");
buttons.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
buttons.add(back);
buttons.setCellWidth(back, "98%");
buttons.add(nextBtn);
buttons.setCellWidth(next, "1%");
buttons.add(cancel);
buttons.setCellWidth(cancel, "1%");
The problem is with this panel width. But if I delete it, all my buttons are left aligned. As a workaround I can use false button, that will be invisible and has cell width = 97%, the cell width of back button is 1%. But this is not what I need, because inspite of small amount of memory this invisible button consumes, it is still a memory :)
What is going wrong with this alignment? Maybe something is wrong with panel width? Hope for your help, thank you in advance.
There is setCellHorizontalAlignment() property in HorizontalPanel. With it you can give alignment to its widgets.
Try following:
buttons.setCellHorizontalAlignment(backButton, HasHorizontalAlignment.ALIGN_RIGHT);
buttons.setCellHorizontalAlignment(nextButton, HasHorizontalAlignment.ALIGN_RIGHT);
buttons.setCellHorizontalAlignment(cancelButton, HasHorizontalAlignment.ALIGN_RIGHT);
You can achieve this much easier using css:
FlowPanel panel = new FlowPanel();
panel.setWidth("100%");
cancel = new Button("Cancel");
cancel.getElement().getStyle().setFloat(Float.RIGHT);
next = new Button("Next");
next.getElement().getStyle().setFloat(Float.RIGHT);
back = new Button("Back");
back.getElement().getStyle().setFloat(Float.RIGHT);
panel.add(back);
panel.add(nextBtn);
panel.add(cancel);

Categories