JavaFx Fill WidthColumn Constraint is not working inside a layout - java

I’m going to add two text fields in a row of Java FX GridPane layout. And I want to fill one text field throughout the available space. If I add GridPane directly to the Scene, then it is working fine. But If I add GridPane to another layout like Group (or any other layout) then fill property is not working correctly.
Following code is working as expected.
public void start(final Stage stage) {
GridPane parent = new GridPane();
TextField addEmail = new TextField();
TextField addFirstName = new TextField();
parent.add(addEmail, 0, 0);
parent.add(addFirstName, 1, 0);
ColumnConstraints cons1 = new ColumnConstraints();
cons1.setFillWidth(true);
cons1.setHgrow(Priority.ALWAYS);
parent.getColumnConstraints().add(cons1);
Scene scene = new Scene(parent, 400, 300, Color.WHITE);
stage.setScene(scene);
stage.show();
}
Following one is not working (But I want to make this work).
public void start(final Stage stage) {
GridPane parent = new GridPane();
TextField addEmail = new TextField();
TextField addFirstName = new TextField();
parent.add(addEmail, 0, 0);
parent.add(addFirstName, 1, 0);
ColumnConstraints cons1 = new ColumnConstraints();
cons1.setFillWidth(true);
cons1.setHgrow(Priority.ALWAYS);
parent.getColumnConstraints().add(cons1);
Group group = new Group();
group.getChildren().addAll(parent);
Scene scene = new Scene(group, 400, 300, Color.WHITE);
stage.setScene(scene);
stage.show();
}
I’m new to Java FX hence my approach may completely wrong please direct me to the correct path.

Sorry, but you've chosen the wrong parent.
From the javadoc of Group:
By default, a Group will "auto-size" its managed resizable children to their preferred sizes during the layout pass to ensure that Regions and Controls are sized properly as their state changes.
A Group simply does not modify the size of it's children other than resizing them to the preferred size.
Only if you put the GridPane in a parent that resizes it, like e.g. StackPane, it's size is modified...

Related

JavaFX -- Creating multiple panes within a scene

So I have to make a Zodiac Sign GUI, and we are tasked with having the following:
a Label in the top left, and a TextField in the top right (both with padding)
an exit Button in the center of the GUI, along with a clear and find my sign on either side
and finally, a Label in the bottom center prompting the sign
I am utterly confused on how to have this come out, as I am a novice in JavaFX. I believe I would need a branch node along with the root node in order to get this kind of layout. I do not need assistance in instantiating the button, labels etc., mainly confused with how this layout can even work. The code I have now is the following:
public class ZodiacGUI extends Application {
public static void main(String args[]) {
Application.launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
BorderPane mainPane = new BorderPane();
mainPane.setStyle("-fx-background-color: PINK");
setupControls(mainPane);
Scene scene = new Scene(mainPane);
setStage(primaryStage, scene);
}
public void setStage(Stage primaryStage, Scene scene) {
primaryStage.setWidth(500);
primaryStage.setHeight(200);
primaryStage.setTitle("What is my Zodiac Sign?");
primaryStage.setScene(scene);
primaryStage.show();
}
public void setupControls(BorderPane mainPane) {
Label label = new Label("Enter you birthday formatted as -> mm/dd");
Button exitButton = new Button();
Button findSign = new Button();
Button clear = new Button();
TextField userInput = new TextField();
userInput.setPromptText("Enter birthday");
exitButton.setText("Exit.");
findSign.setText("Find my sign.");
clear.setText("Clear.");
exitButton.setOnAction(e -> System.exit(0));
mainPane.setLeft(label);
mainPane.setRight(userInput);
mainPane.setCenter(exitButton);
mainPane.setCenter(findSign);
mainPane.setCenter(clear);
BorderPane.setAlignment(label, Pos.TOP_LEFT);
BorderPane.setAlignment(userInput, Pos.TOP_RIGHT);
BorderPane.setAlignment(exitButton, Pos.CENTER);
BorderPane.setAlignment(findSign, Pos.CENTER_LEFT);
BorderPane.setAlignment(clear, Pos.CENTER_RIGHT);
}
}
This only outputs one of the buttons out of the three, as I assume it is because the necessary addition of another BorderPane? Here is a drawn out picture of what I would like to come out with:
Just to clarify, I do not need assistance with the handling of finding the zodiac sign, etc. Mainly need assistance on the layout, as it has stumped me for days. Thank you in advance for helping out a novice to JavaFX :).
You have three rows with diffrent number of children. You can use HBox if row have more than one child.
BorderPane mainPane = new BorderPane();
mainPane.setTop(new HBox(topLabel, topField));
mainPane.setCenter(new HBox(centerLabel, centerField, centerButtom));
mainPane.setBottom(bottomCenterButton);
If you need more than 3 rows (top, center, bottom section of BorderPane) you can use VBox, where every child is row like:
HBox row1 new HBox(child1, child2)
HBox row2 new HBox(child1, child2, child3)
HBox row3 new HBox(child1)
HBox row4 new HBox(child1, child2)
VBox pane = new VBox(row1, row2, row3, row4);
You might want to use a GridPane
GridPane grid = new GridPane();
grid.add(label,0,0);
grid.add(userInput,2,0);
grid.add(findSign,0,1);
grid.add(exitButton,1,1);
grid.add(clear,2,1);
or use a VBox with BorderPane to help with the layout/alignment
BorderPane mainPane, centerPane;
mainPane.setLeft(label);
mainPane.setRight(userInput);
centerPane.setLeft(findSign);
centerPane.setRight(clear);
centerPane.setCenter(exitButton);
BorderPane.setAlignment(label, Pos.LEFT);
BorderPane.setAlignment(userInput, Pos.RIGHT);
BorderPane.setAlignment(exitButton, Pos.CENTER);
BorderPane.setAlignment(findSign, Pos.LEFT);
BorderPane.setAlignment(clear, Pos.RIGHT);
VBox items = new VBox();
items.getChildren().addAll(mainPane, centerPane);

JavaFX ScrollPane setVvalue() not working properly

I am testing the JavaFX ScrollPane class and realized that it is not working as I expect, I don't know why. I have the following code:
public class Client3 extends Application {
int indexMsg = 0;
Button send;
GridPane root;
ScrollPane msgPane;
GridPane msgPaneContent;
FlowPane writePane;
TextField writeMsg;
Scene scene;
#Override
public void start(Stage primaryStage) {
root = new GridPane();
root.setAlignment(Pos.CENTER);
root.setVgap(10);
root.setPadding(new Insets(10, 10, 10, 10));
msgPane = new ScrollPane();
msgPane.setPrefSize(280, 280);
msgPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
msgPaneContent = new GridPane();
msgPaneContent.setPrefWidth(270);
msgPaneContent.setVgap(10);
writePane = new FlowPane(10, 10);
writePane.setAlignment(Pos.CENTER);
writePane.setPrefWidth(280);
writeMsg = new TextField();
writeMsg.setPrefWidth(150);
writeMsg.setPromptText("Write your message");
writePane.getChildren().add(writeMsg);
GridPane.setConstraints(msgPane, 0, 0);
GridPane.setConstraints(writePane, 0, 1);
msgPane.setContent(msgPaneContent);
root.getChildren().addAll(msgPane, writePane);
writeMsg.setOnAction((ev) -> {
if (!writeMsg.getText().isEmpty()) {
TextArea msg = new TextArea(writeMsg.getText());
msg.setMaxWidth(135);
msg.setPrefRowCount(msg.getLength() / 21 + 1);
msg.setWrapText(true);
GridPane.setConstraints(msg, 0, indexMsg);
indexMsg++;
writeMsg.deleteText(0, writeMsg.getText().length());
msgPaneContent.getChildren().add(msg);
msgPane.setVvalue(1.0);
}
});
scene = new Scene(root, 300, 300);
primaryStage.setTitle("Chat App");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Basically, I have a GridPane as the root with a ScrollPane and a GridPane as its children. The ScrollPane has a children GridPane. There is a TextField with an EventHandler which generates a TextArea inside the GridPane (the ScrollPane's children). Each TextArea object is created in the vertical direction, downwards. I want to set the scrollbar always at its maximum value (setVvalue(1.0)) each time a new TextArea is added. The thing is that it doesn't seem to work as it should because the vertical value is never set to the maximum after handling the event, but it seems to be set to the maximum value that it had before handling it (the bottom of the previous TextArea added).
Any solution for this? Thanks in advance.

Assigning JavaFX Label Font from Combobox not working

I am trying to assign the font of a label(node) by selecting the value from a combobox I constructed. The combobox has only a few options, so all of them should be safe to use in this app.
Everything works fine, and all the correct string value from the combobox is being pulled and assigned to the label. But the font in the label doesn't change, and when I output the font from the label the active font is still the system default. I have another method that edits only the fontSize, and that works fine. So it must be the actual string value being invalid. But no error is thrown, and the combobox list names were gotten from the installed fonts on the system.
The Use case and the code is below. What am I missing?
1) Select Font and Click OK changed)
2) Assigned to label (Code snippets)
String font = String.valueOf(combobox_font.getValue());
label.setFont(Font.font(font));
Note: For the sake of my program I'm trying to assign font type and size separately, but I also tried assigning the values with the font size with no luck.
label.setFont(Font.font(font, fontSize)); ///fontSize is a double value gotten from teh textfled above
3) Outbut Label Font (Still System Default)
Font[name=System Regular, family=System, style=Regular, size=12.0]
If you are specifying the font name instead of the family name, you need to use the constuctor of Font, since all the static methods expect the font family:
#Override
public void start(Stage primaryStage) {
ComboBox<String> fontChoice = new ComboBox<>(FXCollections.observableList(Font.getFontNames()));
Spinner<Integer> spinner = new Spinner<>(1, 40, 12);
Text text = new Text("Hello World!");
text.fontProperty().bind(Bindings.createObjectBinding(() -> new Font(fontChoice.getValue(), spinner.getValue()), spinner.valueProperty(), fontChoice.valueProperty()));
HBox hBox = new HBox(fontChoice, spinner);
StackPane.setAlignment(hBox, Pos.TOP_CENTER);
StackPane root = new StackPane(hBox, text);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
To use the static methods, use the family names:
#Override
public void start(Stage primaryStage) {
ComboBox<String> familyChoice = new ComboBox<>(FXCollections.observableList(Font.getFamilies()));
Spinner<Integer> spinner = new Spinner<>(1, 40, 12);
Text text = new Text("Hello World!");
text.fontProperty().bind(Bindings.createObjectBinding(() -> Font.font(familyChoice.getValue(), spinner.getValue()), spinner.valueProperty(), familyChoice.valueProperty()));
HBox hBox = new HBox(familyChoice, spinner);
StackPane.setAlignment(hBox, Pos.TOP_CENTER);
StackPane root = new StackPane(hBox, text);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}

Absolute layout- centering of buttons

I'm working on a project, and I need to make two buttons absolutly centered on the scene.
I haven't found any built in pane option to do the work, so I had to use alot of binding.
The code for that is really long and I'm quite sure there is an easier way to do the job.
Here is a demo: http://screencast.com/t/pvi5WLko
So what I want to know is, if there's an easy way to do the same thing and preferably with built in panes or something.
I want the buttons to be centered, no matter how the window is resized. Example:
The probably easiest way would be to use a VBox:
public void start(final Stage stage) throws Exception {
final Button button0 = new Button("Start learning");
final Button button1 = new Button("Customize");
final VBox box = new VBox();
box.setFillWidth(true);
box.getChildren().setAll(button0, button1);
box.setAlignment(Pos.CENTER);
stage.setScene(new Scene(box));
stage.setWidth(200);
stage.setHeight(100);
stage.show();
}
Another possible way of doing this is with a GridPane:
public void start(final Stage stage) throws Exception {
final Button button0 = new Button("Start learning");
final Button button1 = new Button("Customize");
final GridPane cPane = new GridPane();
cPane.getChildren().addAll(button0, button1);
GridPane.setConstraints(button0, 0, 0, 1, 1, HPos.CENTER, VPos.CENTER);
GridPane.setConstraints(button1, 0, 1, 1, 1, HPos.CENTER, VPos.CENTER);
final ColumnConstraints columnn0 = new ColumnConstraints();
columnn0.setPercentWidth(100);
cPane.getColumnConstraints().addAll(columnn0);
final RowConstraints row0 = new RowConstraints(1);
row0.setPercentHeight(50);
final RowConstraints row1 = new RowConstraints(1);
row1.setPercentHeight(50);
cPane.getRowConstraints().addAll(row0, row1);
stage.setScene(new Scene(cPane));
stage.setWidth(200);
stage.setHeight(100);
stage.show();
}
The idea here would be to configure the rows and columns in the grid to fill your scene using the according constraints objects. The above defines one column and two rows. You can then align your components within the cells of the Grid, using GridPane.setConstraints(...).
You might want to alter the code slightly to have the top button align to VPos.BOTTOM and the lower one to VPos.TOP, depending on whether you want the buttons to stick together (you'll then have to define a margin for both, of course).

Binding BorderPane and Frame Height and Width

I am using JavaFX 2 in Netbeans. How do I get the width and height of an element to adjust when the Frame is resized? Here is my layout:
Stage stage = new Stage();
stage.setTitle("Hello World");
final Group root = new Group();
Scene scene = new Scene(root);
BorderPane border = new BorderPane();
border.setPrefWidth(stage.getWidth());
border.setPrefHeight(stage.getHeight());
HBox outerHBox = new HBox();
border.setCenter(outerHBox);
root.getChildren().add(border);
stage.setScene(scene);
After some more research
I found where this has been done before http://java.dzone.com/articles/setting-stage-javafx-sdk but it is in an older FX (very different from JavaFX 2). I am having trouble translating it. Looks like I should be using binding? I've never used binding before and I've barely used FX.
Whats the best way to accomplish this?
Not all Node classes enable resizing. The Group class is one of these. You'll understand this when calling isResizable() on your root object. Use instead a subclass of Region e.g. BorderPane as your root.
Stage stage = new Stage();
stage.setTitle("Hello World");
final BorderPane border = new BorderPane();
Scene scene = new Scene(border);
Button button = new Button("test");
HBox outerHBox = new HBox();
outerHBox.getChildren().add(button);
outerHBox.setAlignment(Pos.CENTER);
border.setCenter(outerHBox);
stage.setScene(scene);
Your example should work, now.

Categories