Extracting text from dynamically created textfields inside various rows of gridpane - java

I'm trying to create a grid with a textbox on each row where user can enter a number, and corresponding number of new rows are added. This works well, as shown below in the screenshot.
Now I'm trying to extract the text from those textfields created based on the question "how many?" and since they are nested within various node elements, I'm having a hard time identifying the right way.Can anyone tell me what I'm doing wrong? I tried testing it using the save button, but I always go into the else statement of "Vboxgrid2 is empty!"on my console. I don't know why it says that my VBoxgrid2 is empty!
Following is a Minimal, Complete, and Verifiable example I've recreated:
package testing;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ExtractThatText extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("GridPane Experiment");
GridPane gridPane = new GridPane();
for(int i=0;i<5;i++) {
VBox mainVBox = new VBox();
VBox vboxgrid1 = new VBox();
VBox vboxgrid2 = new VBox();
HBox hboxgrid = new HBox();
hboxgrid.setPadding(new Insets(5,5,5,5));
RadioButton rbYes = new RadioButton("Yes");
RadioButton rbNo = new RadioButton("No");
Label howmanyLabel = new Label(" How many? ");
TextField howManytxtB = new TextField();
hboxgrid.getChildren().add(rbYes);
hboxgrid.getChildren().add(rbNo);
hboxgrid.getChildren().add(howmanyLabel);
hboxgrid.getChildren().add(howManytxtB);
vboxgrid1.getChildren().add(hboxgrid);
howManytxtB.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
vboxgrid2.getChildren().clear();
Integer howManyNum = Integer.valueOf(howManytxtB.getText());
for(int row=0;row<howManyNum;row++) {
//creating rows for entering the new entities
HBox innerRowbox = new HBox();
TextField name = new TextField();
ComboBox cb = new ComboBox(); //empty cb for now
name.setPromptText("Enter name of the new Entity");
name.setMinWidth(200);
innerRowbox.getChildren().add(name);
innerRowbox.getChildren().add(cb);
vboxgrid2.getChildren().add(innerRowbox);
}
}
});
mainVBox.getChildren().add(vboxgrid1);
mainVBox.getChildren().add(vboxgrid2);
gridPane.add(mainVBox,1, i);
}
for(int i=0;i<5;i++) {
gridPane.add(new Label("row"+i), 0 , i);
}
Button saveButton = new Button("save content");
saveButton.setOnAction(e-> {
Node mainVBox = gridPane.getChildren().get(1); //get just the first row's 1th column which contains mainVBox
if(mainVBox instanceof VBox) {
Node vboxgrid2 = ((VBox) mainVBox).getChildren().get(1);
if(vboxgrid2 instanceof VBox) {
if(!((VBox) vboxgrid2).getChildren().isEmpty()) {
Node innerRowBox = ((VBox) vboxgrid2).getChildren().get(0);
if(innerRowBox instanceof HBox) {
for(Node howmanyTB:((HBox)innerRowBox).getChildren()) {
if(howmanyTB instanceof TextField) {
System.out.println(((TextField) howmanyTB).getText()); //content to save, extracted from the dnamic textfields created.
}
else System.out.println("howmanyTB not an instance of TextField error!");
}
}
else System.out.println("innerRowBox not an instance of HBox error!");
}
else System.out.println("Vboxgrid2 is empty!");
}
else System.out.println("vboxgrid2 not an instance of VBox error!");
}
else System.out.println("mainVbox not an instance of VBox error!");
});
gridPane.add(saveButton, 1, 5);
gridPane.setHgap(10);
gridPane.setVgap(10);
Scene scene = new Scene(gridPane, 500, 500);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
** If it's difficult to understand the nesting of all my nodes, here is a summary:
gridPane -> mainVBox (in each row of the second/1th column) -> vboxgrid2 (along with vboxgrid1 above it for the radiobutton row in mainVBox) -> innerRowbox -> name (textfield)

If it's difficult to understand the nesting of all my nodes
Since you do seem to realize that your nesting is a bit confusing, it would be preferable to save the TextFields in a data structure that is easier to access than your scene hierarchy. In this case since the number of items is known before they are created, a TextField[][] array could be used, but you could also go for a List<List<TextField>> to allow you to dynamically add (inner) rows.
BTW: since you use index 1 you access the second row, not the first one.
Also using a VBox just to contain your HBox seems unnecessary. You could simply use the HBox directly, since the VBox has no other children.
Label howmanyLabel = new Label(" How many? ");
Better use a margin for this spacing instead of spaces.
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("GridPane Experiment");
GridPane gridPane = new GridPane();
final int rowCount = 5;
TextField[][] textFields = new TextField[rowCount][0];
final Insets hboxPadding = new Insets(5);
final Insets labelMargin = new Insets(0, 15, 0, 15);
for (int i = 0; i < rowCount; i++) {
VBox vboxgrid2 = new VBox();
RadioButton rbYes = new RadioButton("Yes");
RadioButton rbNo = new RadioButton("No");
Label howmanyLabel = new Label("How many?");
HBox.setMargin(howmanyLabel, labelMargin);
TextField howManytxtB = new TextField();
HBox hboxgrid = new HBox(rbYes, rbNo, howmanyLabel, howManytxtB);
hboxgrid.setPadding(hboxPadding);
final int rowIndex = i;
howManytxtB.setOnAction(event -> {
vboxgrid2.getChildren().clear();
int howManyNum = Math.max(0, Integer.parseInt(howManytxtB.getText()));
TextField[] fields = new TextField[howManyNum];
for (int row = 0; row < howManyNum; row++) {
//creating rows for entering the new entities
TextField name = new TextField();
ComboBox cb = new ComboBox(); //empty cb for now
name.setPromptText("Enter name of the new Entity");
name.setMinWidth(200);
HBox innerRowbox = new HBox(name, cb);
vboxgrid2.getChildren().add(innerRowbox);
fields[row] = name;
}
textFields[rowIndex] = fields;
});
VBox mainVBox = new VBox(hboxgrid, vboxgrid2);
gridPane.addRow(i, new Label("row" + i), mainVBox);
}
Button saveButton = new Button("save content");
saveButton.setOnAction(e -> {
TextField[] secondRowFields = textFields[1];
if (secondRowFields.length == 0) {
System.out.println("no TextFields in row1");
} else {
for (TextField textField : secondRowFields) {
System.out.println(textField.getText());
}
}
});
gridPane.add(saveButton, 1, rowCount);
gridPane.setHgap(10);
gridPane.setVgap(10);
Scene scene = new Scene(gridPane, 500, 500);
primaryStage.setScene(scene);
primaryStage.show();
}

In the demo app, I added a List<TextField> textFieldContainer = new ArrayList(); that stores the dynamically create TextFields.
The code below delete the appropriate TextFields if the numbers change and Enter is pressed.
textFieldContainer.removeIf(p -> p.getUserData().toString().startsWith("TextField_" + tempRow));
Full Code:
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ExtractThatText extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
List<TextField> textFieldContainer = new ArrayList();
primaryStage.setTitle("GridPane Experiment");
GridPane gridPane = new GridPane();
for(int i=0;i<5;i++) {
VBox mainVBox = new VBox();
VBox vboxgrid1 = new VBox();
VBox vboxgrid2 = new VBox();
HBox hboxgrid = new HBox();
hboxgrid.setPadding(new Insets(5,5,5,5));
RadioButton rbYes = new RadioButton("Yes");
RadioButton rbNo = new RadioButton("No");
Label howmanyLabel = new Label(" How many? ");
TextField howManytxtB = new TextField();
hboxgrid.getChildren().add(rbYes);
hboxgrid.getChildren().add(rbNo);
hboxgrid.getChildren().add(howmanyLabel);
hboxgrid.getChildren().add(howManytxtB);
vboxgrid1.getChildren().add(hboxgrid);
final Integer tempRow = i;
howManytxtB.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
vboxgrid2.getChildren().clear();
Integer howManyNum = Integer.valueOf(howManytxtB.getText());
//The next two lines clears TextFields if you change the amount and/or press enter
textFieldContainer.removeIf(p -> p.getUserData().toString().startsWith("TextField_" + tempRow));
for(int row=0;row<howManyNum;row++) {
//creating rows for entering the new entities
HBox innerRowbox = new HBox();
TextField name = new TextField();
final Integer innerRow = row;
name.setUserData("TextField_" + tempRow + "_" + innerRow);
System.out.println(name.getUserData().toString());
textFieldContainer.add(name);
ComboBox cb = new ComboBox(); //empty cb for now
name.setPromptText("Enter name of the new Entity");
name.setMinWidth(200);
innerRowbox.getChildren().add(name);
innerRowbox.getChildren().add(cb);
vboxgrid2.getChildren().add(innerRowbox);
}
}
});
mainVBox.getChildren().add(vboxgrid1);
mainVBox.getChildren().add(vboxgrid2);
gridPane.add(mainVBox,1, i);
}
for(int i=0;i<5;i++) {
gridPane.add(new Label("row"+i), 0 , i);
}
Button saveButton = new Button("save content");
saveButton.setOnAction(e-> {
System.out.println("Saving these TextField's Text:");
for(TextField textField : textFieldContainer)
{
System.out.println(textField.getUserData() + ": " + textField.getText());
}
});
gridPane.add(saveButton, 1, 5);
gridPane.setHgap(10);
gridPane.setVgap(10);
Scene scene = new Scene(gridPane, 500, 500);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
Output:
Click save content to see the info currently in the TextFields.
Saving these TextField's Text:
TextField_0_0: one
TextField_1_0: two
TextField_1_1: three
TextField_2_0: four
TextField_3_0: seven
TextField_3_1: six
TextField_4_0: five

Related

How do I create a JavaFX BorderPane with no center?

I would like to create a BorderPane layout in JavaFX with no center pane.
The code I have written so far only implements the left and right borders and is below:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class GUI_Practice extends Application {
#Override
public void start(Stage stage) throws Exception {
String blackBorder = "-fx-border-style: solid; -fx-border-width: 1; -fx-border-color: black";
/* Left column */
Button save = new Button("Save");
Button del = new Button("Delete");
HBox settings = new HBox(save, del);
VBox leftCol = new VBox(settings);
leftCol.setStyle(blackBorder);
/* Right column */
Button calculate = new Button("Calculate");
Button cancel = new Button("Cancel");
HBox runButtons = new HBox(calculate, cancel);
VBox rightCol = new VBox(runButtons);
rightCol.setStyle(blackBorder);
/* Set up borderpane */
BorderPane root = new BorderPane();
root.setPadding(new Insets(15));
root.setLeft(leftCol);
root.setRight(rightCol);
Scene scene = new Scene(root, 800, 600);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
The output it gives is shown in the image below:
However, I want it to look more like this:
Where the left and right columns are equal width and take up the entire width of the window. Additionally, the columns do not change width with the window, so the whitespace in the middle gets bigger as the window gets bigger.
What do I need to change to make the columns fill the width of the window?
(P.S. I'm still learning, so if the solution could avoid FXML (which I don't understand yet), that'd be great)
EDIT: as per #k88's suggestion, my start method now looks like so:
public void start(Stage stage) throws Exception {
String blackBorder = "-fx-border-style: solid; -fx-border-width: 1; -fx-border-color: black";
Button calculate = new Button("Calculate");
Button cancel = new Button("Cancel");
HBox runButtons = new HBox(calculate, cancel);
VBox rightCol = new VBox(runButtons);
rightCol.setStyle(blackBorder);
Button save = new Button("Save");
Button del= new Button("Delete");
HBox settings = new HBox(save, load);
VBox leftCol = new VBox(settings);
leftCol.setStyle(blackBorder);
HBox root = new HBox(leftCol, rightCol);
root.setPadding(new Insets(15));
Scene scene = new Scene(root, 800, 600);
stage.setScene(scene);
stage.show();
}
Giving a window looking like:
There are different ways to get this problem fixed.
If you want to still gain the benefits from BorderPane (like to have top and bottom panes), you can set a HBox/GridPane as the center (without setting left/right).
If you are not bothered about top and bottom layout implementations, then as #k88 suggested, you can use directly HBox or GridPane as your root node.
Using HBox:
HBox.setHGrow(leftCol,Priority.ALWAYS);
HBox.setHGrow(rightCol,Priority.ALWAYS);
HBox root = new HBox();
root.setPadding(new Insets(15));
root.getChildren().addAll(leftCol, rightCol);
Using GridPane:
GridPane root = new GridPane();
ColumnConstraints col1 = new ColumnConstraints();
col1.setPercentWidth(50);
ColumnConstraints col2 = new ColumnConstraints();
col2.setPercentWidth(50);
root.getColumnConstraints().addAll(col1,col2);
root.addRow(0, leftCol,rightCol);
Update: In either cases, if you want your buttons to auto stretch, bind the width of the buttons to its layout. This way you can control the buttons width proportion in the HBox.
Button calculate = new Button("Calculate");
Button cancel = new Button("Cancel");
HBox runButtons = new HBox(calculate, cancel);
calculate.prefWidthProperty().bind(runButtons.widthProperty().divide(2));
cancel.prefWidthProperty().bind(runButtons.widthProperty().divide(2));
Update 2: Please find below a sample demo.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.*;
import javafx.stage.Stage;
public class Sample extends Application {
public void start(Stage stage) throws Exception {
String blackBorder = "-fx-border-style: solid; -fx-border-width: 1; -fx-border-color: black";
Button calculate = new Button("Calculate");
Button cancel = new Button("Cancel");
HBox runButtons = new HBox(calculate, cancel);
calculate.prefWidthProperty().bind(runButtons.widthProperty().divide(2));
cancel.prefWidthProperty().bind(runButtons.widthProperty().divide(2));
VBox rightCol = new VBox(runButtons);
rightCol.setStyle(blackBorder);
Button save = new Button("Save");
Button del = new Button("Delete");
HBox settings = new HBox(save, del);
save.prefWidthProperty().bind(settings.widthProperty().divide(3)); // 1/3
del.prefWidthProperty().bind(settings.widthProperty().divide(3).multiply(2)); // 2/3
VBox leftCol = new VBox(settings);
leftCol.setStyle(blackBorder);
GridPane root = new GridPane();
ColumnConstraints col1 = new ColumnConstraints();
col1.setPercentWidth(50);
ColumnConstraints col2 = new ColumnConstraints();
col2.setPercentWidth(50);
root.getColumnConstraints().addAll(col1,col2);
root.addRow(0, leftCol,rightCol);
Scene scene = new Scene(root, 800, 600);
stage.setScene(scene);
stage.show();
}
public static void main(String... a) {
Application.launch(a);
}
}

Limiting the number of visible rows in a menu: JavaFX

Is there a way to limit the number of visible rows for a menu in JavaFX?
Here is a working example
public class MenuProb extends Application {
public void start(Stage primaryStage) {
Group group = new Group();
Scene scene = new Scene(group, 800, 600);
MenuBar menuBar = new MenuBar();
Menu someValues = new Menu("Values");
for (int i = 0; i < 50; i++) {
MenuItem item = new MenuItem("Value " + i);
someValues.getItems().add(item);
}
menuBar.getMenus().add(someValues);
group.getChildren().addAll(menuBar);
primaryStage.setScene(scene);
primaryStage.show();
}
}
When the above code is run, a menu is created wherein the scrollbar appears only after the menuitems have exceeded the screen height.
Is there a way to limit the number of visible rows to a pre-decided number? That is, a scrollbar appears if the number of rows exceeds that limit.
One approach is to use a CustomMenuItem with a Control that lets you adjust the size. The example below illustrates a ComboBox, which allows setVisibleRowCount(), and a ListView, which includes a prefWidthProperty and prefHeightProperty.
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.CustomMenuItem;
import javafx.scene.control.ListView;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.stage.Stage;
/** #see https://stackoverflow.com/q/44792148/230513 */
public class CustomMenuTest extends Application {
#Override
public void start(Stage primaryStage) {
Group group = new Group();
Scene scene = new Scene(group, 320, 240);
ComboBox<String> comboBox = new ComboBox<>();
for (int i = 0; i < 50; i++) {
comboBox.getItems().add("Value " + i);
}
CustomMenuItem comboMenuItem = new CustomMenuItem(comboBox, false);
comboBox.getSelectionModel().select(0);
comboBox.setVisibleRowCount(16);
ObservableList<String> values = FXCollections.observableArrayList();
for (int i = 0; i < 50; i++) {
values.add("Value " + i);
}
ListView<String> listView = new ListView<>(values);
CustomMenuItem listMenuItem = new CustomMenuItem(listView, false);
MenuBar menuBar = new MenuBar();
Menu comboMenu = new Menu("Combo Values");
comboMenu.getItems().add(comboMenuItem);
Menu listMenu = new Menu("List Values");
listMenu.getItems().add(listMenuItem);
menuBar.getMenus().addAll(comboMenu, listMenu);
group.getChildren().addAll(menuBar);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Java dynamically add items to a listview

Hey guys I have this small problem. I'm a newbie to Java and I just want to figure out "how to add another item at the end of the list view below in my code". This should happen dynamically while the program is running. I just wanna click that appropriate space at the bottom of the listview and just add an item. Could someone please help me on this concern. thanks!
Note: Run the application and everything will appear there. I just want to add functionalities to these buttons. When I click "Add" button, i should be able to add more items.
package layoutsizingaligning;
import java.util.Scanner;
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.scene.control.Control;
import javafx.scene.Scene;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.PasswordField;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.*;
import javafx.stage.Stage;
/**
* Sample application that shows how the sized of controls can be managed.
* Sample is for demonstration purposes only, most controls are inactive.
*/
public class LayoutSizingAligning extends Application {
// Define buttons here for access by multiple methods
private Button btnApply = new Button("Apply");
private Button btnContinue = new Button("Continue");
private Button btnExit = new Button("Exit");
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Application.launch(LayoutSizingAligning.class, args);
}
//#Override
public void start(Stage primaryStage) {
// Make Exit button bigger by using larger font for label
//btnExit.setStyle("-fx-font-size: 12pt;");
// Use tab pane with one tab for sizing UI and one tab for alignment UI
TabPane tabs = new TabPane();
Tab tabSize = new Tab();
tabSize.setText("Sizing");
tabSize.setContent(sizingSample());
Tab tabAlign = new Tab();
tabAlign.setText("Alignment");
tabAlign.setContent(alignmentSample());
tabs.getTabs().addAll(tabSize, tabAlign);
Scene scene = new Scene(tabs, 300, 400); // Manage scene size
primaryStage.setTitle("Sizing and Aligning");
primaryStage.setScene(scene);
primaryStage.show();
}
/*
* Creates the UI for the sizing sample, which demonstrates ways to manage
* the size of controls when you don't want the default sizes.
*/
private Pane sizingSample() {
BorderPane border = new BorderPane();
border.setPadding(new Insets(20, 0, 20, 20));
ListView<String> lvList = new ListView<String>();
ObservableList<String> items = FXCollections.observableArrayList (
"Hot dog", "Hamburger", "French fries",
"Carrot sticks", "Chicken salad");
// Scanner scan = new Scanner(System.in);
// String s = scan.next();
// items.add(s);
lvList.setItems(items);
lvList.setMaxHeight(Control.USE_PREF_SIZE);
lvList.setPrefWidth(150.0);
border.setLeft(lvList);
border.setRight(createButtonColumn());
border.setBottom(createButtonRow()); // Uses a tile pane for sizing
// border.setBottom(createButtonBox()); // Uses an HBox, no sizing
return border;
}
/*
* Creates the UI for the alignment sample, which demonstrates ways to manage
* the alignment of controls when you don't want the default alignment.
*/
private Pane alignmentSample() {
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER); // Override default
grid.setHgap(10);
grid.setVgap(12);
// Use column constraints to set properties for columns in the grid
ColumnConstraints column1 = new ColumnConstraints();
column1.setHalignment(HPos.RIGHT); // Override default
grid.getColumnConstraints().add(column1);
ColumnConstraints column2 = new ColumnConstraints();
column2.setHalignment(HPos.LEFT); // Override default
grid.getColumnConstraints().add(column2);
HBox hbButtons = new HBox();
hbButtons.setSpacing(10.0);
hbButtons.setAlignment(Pos.CENTER); // Aligns HBox and controls in HBox
Button btnSubmit = new Button("Submit");
Button btnClear = new Button("Clear");
Button btnExit2 = new Button("Exit");
//btnSubmit.setStyle("-fx-font-size: 15pt;");
Label lblName = new Label("User name:");
TextField tfName = new TextField();
Label lblPwd = new Label("Password:");
PasswordField pfPwd = new PasswordField();
hbButtons.getChildren().addAll(btnSubmit, btnClear, btnExit2);
grid.add(lblName, 0, 0);
grid.add(tfName, 1, 0);
grid.add(lblPwd, 0, 1);
grid.add(pfPwd, 1, 1);
grid.add(hbButtons, 0, 2, 2, 1);
/* Uncomment the following statements to bottom-align the buttons */
// hbButtons.setAlignment(Pos.BOTTOM_CENTER);
// GridPane innergrid = new GridPane();
// innergrid.setAlignment(Pos.CENTER);
// innergrid.add(hbButtons, 0, 0);
// grid.add(innergrid, 0, 2, 2, 1);
return grid;
}
/*
* Creates a column of buttons and makes them all the same width as the
* largest button.
*/
private VBox createButtonColumn() {
Button btnAdd = new Button("Add");
Button btnDelete = new Button("Delete");
Button btnMoveUp = new Button("Move Up");
Button btnMoveDown = new Button("Move Down");
// Comment out the following statements to see the default button sizes
btnAdd.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
btnDelete.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
btnMoveUp.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
btnMoveDown.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
btnMoveDown.setMinWidth(Control.USE_PREF_SIZE);
btnAdd.setOnAction(new EventHandler<ActionEvent>() {
//#Override
public void handle(ActionEvent event) {
Scanner scan = new Scanner(System.in);
String s = scan.next();
}
});
VBox vbButtons = new VBox();
vbButtons.setSpacing(10);
vbButtons.setPadding(new Insets(0, 20, 10, 20));
vbButtons.getChildren().addAll(
btnAdd, btnDelete, btnMoveUp, btnMoveDown);
return vbButtons;
}
/*
* Creates a row of buttons and makes them all the same size.
*/
private TilePane createButtonRow() {
// Let buttons grow, otherwise they will be different sizes based
// on the length of the label
btnApply.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
btnContinue.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
btnExit.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
btnExit.setOnAction(new EventHandler<ActionEvent>() {
//#Override
public void handle(ActionEvent event) {
System.exit(0);
}
});
TilePane tileButtons = new TilePane(Orientation.HORIZONTAL);
tileButtons.setPadding(new Insets(20, 10, 20, 0));
tileButtons.setHgap(10.0);
tileButtons.setVgap(8.0); // In case window is reduced and buttons
// require another row
tileButtons.getChildren().addAll(btnApply, btnContinue, btnExit);
return tileButtons;
}
/*
* Creates a row of buttons with the default sizes.
*/
private HBox createButtonBox() {
HBox hbButtons = new HBox();
hbButtons.setSpacing(10);
hbButtons.setPadding(new Insets(20, 10, 20, 0));
hbButtons.getChildren().addAll(btnApply, btnContinue, btnExit);
return hbButtons;
}
}
First of all, you need to put your ListView in an accessible place, so that you can find the reference again later. Thus, do not declare it as a local variable, but as a field.
Then, to add an item, you simply do:
listview.getItems().add("some new element");

JavaFX setTabcontent dynamically

I have made an application which uses tabpane. I am able to set tooltip and title of each tab dynamically. But how do I set its contents dynamically. I am sure that I can maintain a list of Node object and add it to tab during iteration, but I feel there are other ways to do it. Here is what I have done so far.
public class Index extends Application {
public static void main(String[] args) {
launch(args);
}
final String[] tabContent={"title1"
,"title2"
,"title3"
,"title4"
,"title5"};
final String[] tabToolTip={"tooltip1"
,"tooltip2"
,"tooltip3"
,"tooltip4"
,"tooltip5"};
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Ipas Utility");
Group root = new Group();
Scene scene = new Scene(root, 1000, 600, Color.ALICEBLUE);
TabPane tabPane = new TabPane();
tabPane.setTooltip(new Tooltip("Hover on each tab for an overview"));
BorderPane borderPane = new BorderPane();
for (int i = 0; i < 5; i++) {
Tab tab = new Tab();
tab.setText(tabContent[i]);
tab.setClosable(false);
tab.setTooltip(new Tooltip(tabToolTip[i]));
HBox hbox = new HBox();
hbox.getChildren().add(new Label(tabContent[i]));
hbox.setAlignment(Pos.CENTER);
tab.setContent(hbox);;
tabPane.getTabs().add(tab);
}
// bind to take available space
borderPane.prefHeightProperty().bind(scene.heightProperty());
borderPane.prefWidthProperty().bind(scene.widthProperty());
borderPane.setCenter(tabPane);
root.getChildren().add(borderPane);
primaryStage.setScene(scene);
primaryStage.show();
}
}
How I can maintain tabcontent in a list/array outside start block?
That's quite okay what you did. Here's a modified version of your code which allows you to add a tab on button click:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Main extends Application {
private static int tabCount = 0;
#Override
public void start(Stage primaryStage) {
TabPane tabPane = new TabPane();
tabPane.getTabs().add(createTab());
tabPane.getTabs().add(createTab());
tabPane.getTabs().add(createTab());
Button addTabButton = new Button( "Add Tab");
addTabButton.setOnAction(e -> {
tabPane.getTabs().add(createTab());
});
Button logButton = new Button( "Log");
logButton.setOnAction(e -> {
for( Tab tab: tabPane.getTabs()) {
System.out.println( "Tab " + tab.getText() + " has content " + tab.getContent());
}
});
HBox toolbar = new HBox();
HBox.setMargin(addTabButton, new Insets(5,5,5,5));
HBox.setMargin(logButton, new Insets(5,5,5,5));
toolbar.getChildren().addAll( addTabButton, logButton);
BorderPane root = new BorderPane();
root.setTop(toolbar);
root.setCenter(tabPane);
Scene scene = new Scene(root, 640, 480);
primaryStage.setScene(scene);
primaryStage.show();
}
public static Tab createTab() {
tabCount++;
Tab tab = new Tab();
tab.setText("Tab " + tabCount);
tab.setTooltip( new Tooltip( "Tooltip Tab " + tabCount));
Node content = new Label( "Content Tab " + tabCount);
tab.setContent(content);
return tab;
}
public static void main(String[] args) {
launch(args);
}
}
In order to access the tabs you can use getTabs. And in order to change the content, i. e. the node that represents the content, you can use setContent.
The example code shows you how to iterate through the tabs by pressing the log button.

what is the best way to layout my checkboxes in javafx?

I am trying to achieve this design using css and javafx and so far i think im on the right track, but where i am stuck at is the check boxes.I cant seem to get them to layout correctly and functioning the way i want them to. I put 4 check Boxes in each of the two vboxs and put them both in the same cell to be able fit in one border that i set in the style sheet,but when i do this only the second column of check boxes work. I have tried other options such as using a second gridPane and laying out the check boxes in there then putting the second gridPane in the gridPane that i set for the scene, but that wouldn't even run so my question is what is the best way to layout my check boxes so they look like this and are functioning properly? Here is what i have so far
import javafx.scene.*;
import javafx.stage.*;
import javafx.geometry.*;
import javafx.application.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.collections.*;
import javafx.event.*;
import javafx.scene.text.TextAlignment;
public class ClassRegistrationForm extends Application{
Scene scene1;
Button createRequestButton,clearButton;
Label peLabel,mathLabel,electivesLabel,englishLabel,spaceLabel;
RadioButton english12,english11,english10,english9;
ToggleGroup group;
ComboBox<String>electivesComboBox;
CheckBox healthBox,sportsBox,liftingBox,aerobicsBox,
archeryBox,swimmingBox,yogaBox,bowlingBox;
HBox buttonHbox;
VBox englishVbox,mathVbox,electivesVbox,peVbox1,peVbox2;
GridPane peClassesGridPane;
ListView<String> mathClassesListView;
ObservableList<String> mathClassesList;
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Class Registration Application");
primaryStage.setResizable(false);
primaryStage.sizeToScene();
GridPane gridPane = new GridPane();
peClassesGridPane = new GridPane();
scene1 = new Scene(gridPane);
buttonHbox = new HBox();
createRequestButton = new Button("Create Request");
clearButton = new Button("Clear");
buttonHbox.getChildren().addAll(createRequestButton,clearButton);
gridPane.setConstraints(buttonHbox,0,2);
peLabel = new Label("Pe");
peClassesGridPane.setConstraints(peLabel,0,0);
healthBox = new CheckBox("Health");
peClassesGridPane.setConstraints(healthBox,0,1);
yogaBox = new CheckBox("Yoga");
peClassesGridPane.setConstraints(yogaBox,0,2);
sportsBox = new CheckBox("Sports");
peClassesGridPane.setConstraints(sportsBox,0,3);
archeryBox = new CheckBox("Archery");
peClassesGridPane.setConstraints(archeryBox,0,4);
spaceLabel = new Label("");
peClassesGridPane.setConstraints(spaceLabel,1,0);
liftingBox = new CheckBox("Lift");
peClassesGridPane.setConstraints(liftingBox,1,1);
swimmingBox = new CheckBox("Swim");
peClassesGridPane.setConstraints(swimmingBox,1,2);
aerobicsBox = new CheckBox("Aero");
peClassesGridPane.setConstraints(aerobicsBox,1,3);
bowlingBox = new CheckBox("Bowl");
peClassesGridPane.setConstraints(bowlingBox,1,4);
peClassesGridPane.getChildren().addAll(
peLabel,healthBox,yogaBox,sportsBox,archeryBox,spaceLabel,
liftingBox,swimmingBox,aerobicsBox,bowlingBox
);
gridPane.setConstraints(peClassesGridPane,0,1);
mathVbox = new VBox();
mathVbox.setAlignment(Pos.CENTER);
mathVbox.setPrefSize(150,100);
mathClassesListView = new ListView();
mathClassesListView.setPrefSize(100,50);
mathClassesList = FXCollections.observableArrayList(
"Algebra 1-2",
"Algebra 3-4",
"Geometry",
"Pre-Calculus",
"Calculus"
);
mathClassesListView.setItems(mathClassesList);
mathLabel = new Label("Math Classes");
mathVbox.getChildren().addAll(mathLabel,mathClassesListView);
gridPane.setConstraints(mathVbox,1,1);
englishVbox = new VBox();
englishVbox.setPrefSize(200, 200);
englishVbox.setAlignment(Pos.CENTER);
group = new ToggleGroup();
englishLabel = new Label("English Classes");
englishVbox.getChildren().add(englishLabel);
english12 = new RadioButton("English12");
english12.setToggleGroup(group);
englishVbox.getChildren().add(english12);
english11 = new RadioButton("English11");
english11.setToggleGroup(group);
englishVbox.getChildren().add(english11);
english10 = new RadioButton("English12");
english10.setToggleGroup(group);
englishVbox.getChildren().add(english10);
english9 = new RadioButton("English9");
english9.setToggleGroup(group);
englishVbox.getChildren().add(english9);
gridPane.setConstraints(englishVbox,0,0);
electivesVbox = new VBox();
electivesVbox.setAlignment(Pos.CENTER);
electivesLabel = new Label("Electives");
ObservableList<String> data = FXCollections.observableArrayList("Java"
, "Web Design"
, "Welding"
, "Woods"
, "Art"
, "Band"
, "GameDesign"
, "Graphic Arts");
electivesComboBox = new ComboBox<String>();
electivesComboBox.setItems(data);
electivesVbox.getChildren().addAll(
electivesLabel,electivesComboBox
);
gridPane.setConstraints(electivesVbox,0,1);
gridPane.getChildren().addAll(
englishVbox,electivesVbox,peVbox1,peVbox2,mathVbox,
buttonHbox,peClassesGridPane
);
primaryStage.setScene(scene1);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
You don't initialize peClassesGridPane. Just add in the line
peClassesGridPane = new GridPane();
before you use it. Additionally, remove the redundant peVBox1 and peVBox2 from the code entirely.

Categories

Resources