When this class runs, the Text that is generated on the bottom (After the button is pressed) is pushing the other controls away from each other and compressing them. Is there any way that I can keep the Text but not have the controls above it compressed? NOTE: This class can be run by calling Application.launch(CSSTrial1.class); from outside the class.
public class CSSTrial1 extends Application {
#Override
public void start(Stage stage) throws Exception {
stage.setTitle("CSS Trial");
stage.setResizable(false);
final GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(25));
grid.add(new Label("Character Name:"), 0, 0);
final TextField nameField = new TextField("");
nameField.setPromptText("Randel James");
grid.add(nameField, 1, 0);
grid.add(new Label("Weapon:"), 0, 1);
final ComboBox<String> weapons = new ComboBox<>();
weapons.getItems().addAll("Katsuragi x2", "Assault Rifle",
"Pistol", "RPG-7", "Barret 50. Cal");
grid.add(weapons, 1, 1);
HBox box = new HBox(10);
box.setAlignment(Pos.BOTTOM_RIGHT);
Button submit = new Button("Submit Character");
submit.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
grid.add(new Text("Signed In As: " + nameField.getText()
+ ", Weapon: " + weapons.getValue()), 0, 6);
}
});
box.getChildren().add(submit);
grid.add(box, 1, 3);
Scene scene = new Scene(grid, 300, 275);
stage.setScene(scene);
stage.show();
}
}
Define a ColumnConstraints object, and use it in the grid pane:
ColumnConstraints firstColumn = new ColumnConstraints();
grid.getColumnConstraints().addAll(firstColumn);
You can set the min, pref, and max width on the column constraints to control how much that column is allowed to be resized (for example, setting all three to the same fixed value will force the column to be that size).
You might also want to set the wrapping width of your text, so that it takes up less space.
According to the Javadocs:
By default, rows and columns will be sized to fit their content; a column will be wide enough to accommodate the widest child, a row tall enough to fit the tallest child.
Since you are adding the nameField to the first column, when the length of that text expands, the whole columns expands in length, causing the "pushing of the controls away from each other." I would suggest either creating a new Pane, have the nameField span two columns, or using a different layout. You may even want to consider using FXML with the JavaFX Scene Builder.
Maybe try to insert the text with another column span such as in this altered code:
submit.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
grid.add(new Text("Signed In As: " + nameField.getText()
+ ", Weapon: " + weapons.getValue()), 0, 6,2,1);//colum span=2, but row span is1
}
});
Related
I am trying to make a basic login screen in javafx using the GridPane layout. The issue is that all the labels I put onto the grid are going to position (0,0) seemingly ignoring my values for the column and row indices.
I've tried putting extreme values for the indices into both function calls and nothing moves. It seems to ignore any indices I give it and defaults to (0,0).
GridPane setup:
GridPane grid = new GridPane();
grid.setPadding(new Insets(10, 10, 10, 10));
grid.setVgap(10);
grid.setHgap(10);
The function calls for the Labels:
// Name label
Label nameLabel = new Label("Username:");
GridPane.setConstraints(grid, 0, 0);
// Password label
Label passLabel = new Label("Password:");
GridPane.setConstraints(grid, 0, 1);
Adding GridPane to scene:
grid.getChildren().addAll(nameLabel, nameInput, passLabel, passInput, loginButton);
Scene scene = new Scene(grid, 300, 200);
You are using GridPane.setConstraints(); incorrectly. Instead of setting the constraints on grid, you should be setting the constraints on the nodes. Examples:
// Name label
Label nameLabel = new Label("Username:");
GridPane.setConstraints(nameLabel, 0, 0);
// Password label
Label passLabel = new Label("Password:");
GridPane.setConstraints(passLabel, 0, 1);
See javadocs for more details.
I am currently developing a messenger in javafx. my general layout is a gridpane with a customized Vbox containing a ListView and a Textfield. The problem is that as you can see below there is a big emty area beneath the textfield. I already tried setting the rowspan to 2, which didn't work.
The important Code:
Main:
chatBox = new ChatBox();
gridPane.add(chatBox, 1, 0, 1, 2);
ChatBox(extends Vbox):
private static ListView<Message> messages;
private TextField inputField;
public ChatBox() {
inputField = new TextField();
messages = new ListView<>();
init();
getChildren().addAll(messages, inputField);
}
Try adding this in the ChatBox class:
VBox.setVgrow(messages, Priority.ALWAYS);
And add this in the main class:
GridPane.setVgrow(chatBox, Priority.ALWAYS);
You need to set the vgrow using RowConstraints. Assuming your first row contains the ListView that is supposed to take all the available space:
RowConstraints constraints = new RowConstraints();
constraints.setVgrow(Priority.ALWAYS);
gridPane.getRowConstraints().addAll(constraints, new RowConstraints());
In order to force the list view to take all the height available in its parent, you can use the following method:
messages.setMaxHeight(Double.MAX_VALUE);
If the problem comes from the VBox, its maxHeight can also be modified with the same method.
In messages apps, as you type a counter label on the corner gets updated showing the number of characters being entered. How do I create the same thing in Java?
Retrieve a IntegerBinding from the TextField's text property containing it's length and convert this to a StringBinding in a way that suits your needs. Bind the text property of the output Label to the result:
#Override
public void start(Stage primaryStage) {
TextField textField = new TextField();
Label label = new Label();
label.textProperty().bind(textField.textProperty()
.length()
.asString("Character Count: %d"));
VBox root = new VBox(label, textField);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public void start(Stage stage) throws Exception {
FlowPane flowPane = new FlowPane();
flowPane.setOrientation(Orientation.VERTICAL);
for(int i = 0; i < 101;i++) {
Label aLabel = new Label("Label number: " + i);
flowPane.getChildren().add(aLabel);
}
Scene applicationScene = new Scene(flowPane);
stage.setHeight(400.0);
stage.setWidth(400.0);
stage.setScene(applicationScene);
stage.show();
}
I am trying to write the code so that all of the labels end up in the same column even though the labels will not be within the window (I plan on adding a scrollPane to make the labels still viewable issue). However, I have no clue as to why, since the labels automatically begin filling up the next column when the first one is filled (example here). How should I go about this?
I have no clue as to why since the labels automatically begin filling
up the next column when the first one is filled
That's the functionality of a FlowPane. From the documentation:
FlowPane lays out its children in a flow that wraps at the flowpane's
boundary. ... A vertical flowpane lays out nodes in columns, wrapping at the flowpane's height.
You should use a VBox instead:
public void start(Stage stage) throws Exception {
VBox vbox = new VBox();
for(int i = 0; i < 101;i++) {
Label aLabel = new Label("Label number: " + i);
vbox.getChildren().add(aLabel);
}
Scene applicationScene = new Scene(vbox);
stage.setHeight(400.0);
stage.setWidth(400.0);
stage.setScene(applicationScene);
stage.show();
}
If you have a lot of data to display, you might also consider using a ListView. The ListView has a more complex API (it manages selection, and can be editable if you choose), and provides its own scrollbars when needed, but it can be more efficient for large amounts of data (basically it only creates UI controls for the visible data, and reuses them as the user scrolls).
I am trying to print the numbers in the horizontal and then show in reverse order, now, in the following code below, the logic is correct and show the number on the console, imrpimi okay, as shown in the second link and show these same values in a label in JavaFX, shows the opposite of the desired solution
public class GridPane extends Application {
#Override
public void start(Stage primaryStage) {
GridPane root = new GridPane();
root.setPadding(new Insets(5));
root.setAlignment(Pos.CENTER);
for (int number = 8; number > 0; number--) {
StringBuilder str = new StringBuilder();
str.append(number);
Label label = new Label(str.toString());
System.out.println(str.toString());
label.setFont(Font.font("Arial", FontWeight.BOLD, 13));
label.setPrefSize(20, 20);
root.add(label,0, number + 3);
}
Scene scene = new Scene(root, 900, 900);
primaryStage.setTitle("Grid Pane Example");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
to test the program, I got is output http://i.imgur.com/Jeh0zWp.jpg
the goal is to follow this logic in which the console displays the result correctly like this http://i.imgur.com/jH9jAs1.jpg
Any suggestions, I appreciate and thanks.
The parameters to root.add(...) are the node you are adding, the column index, and the row index. So you are always adding the label displaying number in row number + 3: i.e. 8 goes in row 11, 7 goes in row 10, etc.
The order of iteration makes no difference.
If you want 1 in row 11, 2 in row 10, 3 in row 9, etc, then you would have to notice that rowIndex = 12 - number and call
root.add(label, 0, 12 - number);