Button and Textfield resizing and aligning - java

I built a calculator. I was not able to align the buttons, and the textfield of the calculator in the form that I desire.
I used GridPane due to the fact that I thought it would be easier to control the buttons. I read Oracle's documents online and I still can't figure this out.
How do you resize/align buttons and textfields in JavaFX?
I used HBox for the textfield, because it is only one figure and it is the easiest way to control it.
The calculator itself works, the problem is the resizing and aligning of the buttons and textfield.
Here's a picture of my calculator:
Here are pieces of my code that control the GridPane:
GridPane grid = new GridPane();
grid.setPadding(new Insets(10 ,10 ,10 ,10));
grid.setVgap(4);
grid.setHgap(4);
HBox topMenu = new HBox(); // Display -- top of the window
grid.getChildren().addAll(button0, button1, button2, button3, button4, button5, button6, button7, button8, button9, plusButton, subButton, multiButton, divButton, eqButton, clearButton,npButton,decButton,percentButton);
topMenu.getChildren().add(display);
BorderPane borderPane = new BorderPane();
borderPane.setTop(topMenu);
borderPane.setCenter(grid);
Scene scene = new Scene(borderPane, 800, 600);
window.setScene(scene);
window.show();

Related

Unsure as to why buttons will not align adjacent to each other in Java FX

I am new to java fx. I am creating a basic GUI which is meant to look like this:
However, when I try my image looks like this:
I am unsure as to why there is a large gap between the two buttons. I am using the grid pane format.
Here is my code:
public class Main extends Application {
#Override
public void start(Stage stage) {
//Creating Text field
TextField textField1 = new TextField();
//Creating Buttons
Button submit = new Button("Submit");
Button cancel = new Button("Cancel");
//Creating a Grid Pane
GridPane gridPane = new GridPane();
//Setting size for the pane
gridPane.setMinSize(200, 100);
//Setting the padding
gridPane.setPadding(new Insets(10, 10, 10, 10));
//Setting the vertical and horizontal gaps between the columns
gridPane.setVgap(5);
gridPane.setHgap(1);
//Setting the Grid alignment
gridPane.setAlignment(Pos.CENTER);
//Arranging all the nodes in the grid
gridPane.add(textField1, 0, 0);
gridPane.add(submit, 0, 1);
gridPane.add(cancel, 1,1);
//Creating a scene object
Scene scene = new Scene(gridPane);
//Setting title to the Stage
stage.setTitle("Simple Form");
//Adding scene to the stage
stage.setScene(scene);
//Displaying the contents of the stage
stage.show();
}
public static void main(String args[]){
launch(args);
}
}
Help would be appreciated :-)
What happens here is that your TextField is set in the top-left corner (0,0), but only spans a single column. You can see that the cancel Button, which is in the bottom right corner (1,1), starts where the TextField stops (if you look only at the x-position).
There is a debug option for GridPanes so you can visualize more what happens. Just call
gridPane.setGridLinesVisible(true):
The solution for this is to set the TextField to obtain/span 2 columns. You can do so by either calling:
GridPane.setColumnSpan(textField1, 2);
Or use a different add method:
gridPane.add(textField1, 0, 0, 2, 1);
See https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/GridPane.html for more information about how the GridPane works.

ScrollPane scroll does not work with other nodes

I want to have StackPane as my root pane. I want to have a scrollPane as a small box in the middle of the scene and two buttons below the container.
I tried to make it happen by writing this code:
private StackPane root = new StackPane();
private Scene scene = new Scene(root, 1366, 768);
public ContinueScreen() {
Button button1 = new ButtonBuilder("My Button1").setPrefWidth(200).build();
Button button2 = new ButtonBuilder("My Button2").setPrefWidth(200).build();
Button button3 = new ButtonBuilder("My Button3").setPrefWidth(200).build();
Button button4 = new ButtonBuilder("My Button4").setPrefWidth(200).build();
Button button5 = new ButtonBuilder("My Button5").setPrefWidth(200).build();
Button button6 = new ButtonBuilder("My Button6").setPrefWidth(200).build();
VBox vBox = new VBox(5);
vBox.getChildren().addAll(button1, button2, button3, button4, button5, button6);
ScrollPane scrollPane = new ScrollPane();
scrollPane.setContent(vBox);
scrollPane.setPannable(true);
scrollPane.setMaxSize(500, 180);
scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
root.getChildren().add(scrollPane);
StackPane.setAlignment(scrollPane, Pos.CENTER);
}
As you can probably notice, the code does work perfectly fine but that is until I add the buttons below I was talking about. I added those buttons in an HBox as
HBox hBox = new HBox(5);
hBox.setAlignment(Pos.BOTTOM_CENTER);
hBox.getChildren().addAll(new Button("cat"), new Button("dog"));
root.getChildren().addAll(hBox);
Now both the scrollpane and the two buttons are shown. However the scroll pane now stops working for some reason. The scrollpane is shown and its content but the horizontal or the vertical scroll, both of them do not work. Anyone knows why is this happening and how to fix it?
As you are using StackPane as root it piles up the nodes on one another so the top pane is HBox and not the ScrollPane, so it you are not able to use.
Use BorderPane or VBox and try.
BorderPane root = new BorderPane();
Scene scene = new Scene(root, 1366, 768);
root.setCenter(scrollPane);
HBox hBox = new HBox(5);
hBox.getChildren().addAll(new Button("cat"), new Button("dog"));
root.setBottom(hBox);
The issue here is that StackPane is allowed to resize the HBox, which it does. The HBox covers the complete scene preventing mouse events from reaching the ScrollPane. You can easily see this by coloring the HBox:
hBox.setStyle("-fx-background-color: rgba(100%, 0%, 0%, 0.5)");
The most simple solution would be to set up the HBox to only receive events on non-(fully-)transparent areas:
hBox.setPickOnBounds(false);
However you could also set up the HBox to take up the space required to fit the preferred size of the content and do the alignment via the StackPane:
hBox.setPrefSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE);
hBox.setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
StackPane.setAlignment(hBox, Pos.BOTTOM_CENTER);
// hBox.setAlignment(Pos.BOTTOM_CENTER);
Note that using a StackPane like this does not provide you with a responsive GUI: If you resize the window to a small enough height, the buttons will cover the ScrollPane.
You may have better luck using a BorderPane or wrapping the StackPane and the HBox in a VBox and setting VBox.vgrow to Priority.ALWAYS for the StackPane...

javafx don't loss the focus when click other node

I have a vbox on left of rootpane,and a vbox on right of rootpane.
leftvobx have 3 textarea nodes,rightvbox have a colorpicker;
I want: when I choose one textarea node on leftvbox, then to click colorpicker on rightvbox, the current textarea don't loss the focus.
My idea is same as "Scene builder" , when we select a note in the workspace, then to handle the right slide function area(like change color,set size and font),the note will not lose focus, so the action know which node in workspace need handle.
Code:
VBox leftBox = new VBox();
VBox rightBox = new VBox();
leftBox.setPrefSize(200, 250);
rightBox.setPrefSize(200, 250);
leftBox.setStyle("-fx-background-color:blue");
Button btn1 = new Button("First");
Button btn2 = new Button("Second");
Button btn3 = new Button("Third");
ColorPicker colorpicker = new ColorPicker();
leftBox.getChildren().addAll(btn1,btn2,btn3);
rightBox.getChildren().add(colorpicker);
colorpicker.setOnAction(e->{
if(btn2.isFocused()){
btn2.setText("color changed.");
}
});
HBox root = new HBox();
root.getChildren().addAll(leftBox,rightBox);
Scene scene = new Scene(root, 400, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
enter image description here
There is no way to have two nodes focused afaik. That would be very weird, since every keyboard event etc would go to two nodes. In the JavaFX scene builder as well, you can try it. Click on something in the SceneBuilder and press delete, it will be deleted. Press on something in the SceneBuilder and then on the right and press delete and the item you selected first will not be deleted. Because it doesn't actually have focus. SceneBuilder just shows you what you had last selected.
To solve your problem. I would make a new Variable Button lastFocused; and make Listeners on the other Buttons focusedProperty something like this:
btn2.focusedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
if(!newValue) lastFocused = btn2;
});
This should store the Button in the new variable as soon as it looses focus. As it looses focus when you focus the color picker, the variable will have the Button that was selected when the color picker got selected.
Now in the color picker something like this should work:
colorpicker.setOnAction(e->{
lastFocused.setText("color changed.");
lastFocused.requestFocus();
});
I have not actually tested the code.

JavaFX Have multiple Panes in one scene?

I am trying to make an application which will have a date at the top (always automatically centered) and content at the bottom which is not going to be aligned to any direction.
I figured the best way to do this would be to have:
Pane normalLayout = new Pane();
StackPane centeredLayout = new Stackpane();
Label centeredText = new Label("I want this text centered!");
Button unorganizedButton = new Button("Press me");
centeredLayout.getChildren().add(centeredText);
normalLayout.getChildren().add(unorganizedButton);
But then I can't do something like:
Scene myScene = new Scene(centeredLayout, normalLayout, 500, 500);
Window myWindow = new Window();
myWindow.setScene(myScene);
myWindow.show();
So how can this be done? How can multiple panes exist on the same scene?
The Scene it self can only have one root Pane.
So if you want 2 panes in the Scene you need 3.
Scene
|
V
Root Pane (Vbox for example)
| |
V V
Pane1 Pane2
In your code this can look like this:
StackPane rootPane = new StackPane();
Scene scene = new Scene(rootPane,...);
Pane pane1 = new Pane();
Pane pane2 = new Pane();
rootPane.getChildren().addAll(pane1,pane2);
Depending on how your Application should be layouted you have to choose the right Pane implementations.
As a little Tip to get familiar whit all the Layout Containers try the SceneBuilder Application. http://gluonhq.com/open-source/scene-builder/
Maybe this link will help you understanding how layouting works in JavaFX:
http://docs.oracle.com/javafx/2/scenegraph/jfxpub-scenegraph.htm
https://docs.oracle.com/javafx/2/layout/builtin_layouts.htm
I would suggest you to create a "root"-Pane.
In your case, you could use a BorderPane.
Example:
BorderPane root = new BorderPane();
Label centeredText = new Label("I want this text centered!");
Button unorganizedButton = new Button("Press me");
BorderPane.setAlignment(centeredText, Pos.CENTER);
root.setTop(centeredText);
root.setBottom(unorganizedButton);
Afterwards just call the constructor with the newly created pane.
Scene scene = new Scene(root, 500, 500);
Addition:
You could also just set new panes.
AnchorPane anchorPane = new AnchorPane();
root.setTop(anchorPane);

How to make TreeView resize as much as parent ScrollPane is?

I have TreeView placed as content of ScrollPane. ScrollPane is placed inside SplitPane.
When I drag divider of SplitPane so that it becomes bigger than TreeView size I see border of TreeView.
I want TreeView to be resized as much as space is available after I drag divider of SplitPane. My code:
SplitPane splitPane = new SplitPane();
splitPane.getItems().addAll(createTreeOfConnections());
private ScrollPane createTreeOfConnections() {
ScrollPane scrollPane = new ScrollPane();
scrollPane.setMinSize(100, 300);
scrollPane.setPrefSize(200, 500);
scrollPane.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
scrollPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
scrollPane.setHbarPolicy(ScrollBarPolicy.AS_NEEDED);
scrollPane.setContent(new ConnectionsTree(this));
return scrollPane;
Class ConnectionsTree extends TreeView and its constructor is :
public ConnectionsTree(MainStage mainStage) {
// here we set the root of ConnectionsTree which is not visible
super();
this.mainStage = mainStage;
root = new ConnectionTreeItem();
root.setExpanded(true);
super.setRoot(root);
super.setShowRoot(false);
super.setEditable(false);
super.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
super.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
retrieveExistentConnectionsNodes();
ContextMenu contextMenu = new ContextMenu(createNewConnectionMenuItem(
"New Connection", KeyCombination.valueOf("Ctrl+N")));
super.setContextMenu(contextMenu); }
How to tell TreeView(my TreeConnections) that it should take all available space of left part of SplitPane?
Thank you!
Try this
scrollPane.setFitToHeight(true);
scrollPane.setFitToWidth(true);

Categories

Resources