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

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.

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);
}
}

Extracting text from dynamically created textfields inside various rows of gridpane

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

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.

Bookmarks and History Buttons not showing up in my Browser using JavaFX

I am making a web browser in JavaFX and I thought everything was good and dandy. I ran the application and now the History and Bookmarks buttons will not appear. I looked through the code and saw no errors. How do I fix this?
package javafxapplication3;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.application.Application;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebHistory;
public class CreateAsIGo2 extends Application{
public static void main(String[] args){
launch(args);
}
public void start(Stage primaryStage){
BorderPane ap = new BorderPane();
BorderPane ap2 = new BorderPane();
BorderPane ap3 = new BorderPane();
Scene scene = new Scene(ap, 700, 700);
Scene scene2 = new Scene(ap2, 700, 700);
Scene scene3 = new Scene(ap3, 700, 700);
VBox sp = new VBox();
VBox sp2 = new VBox();
VBox sp3 = new VBox();
Button HistoryButton = new Button("History");
Button BookmarksButton = new Button("Bookmarks");
Button RefreshButton = new Button("Refresh");
Button BackButton = new Button("Back");
Button BackToBrowser = new Button("Back to surfing the web");
Button ForwardButton = new Button("Forward");
TextField tf = new TextField();
tf.setPromptText("URL");
WebView browser = new WebView();
WebEngine webEngine = browser.getEngine();
webEngine.load("http://www.google.com");
webEngine.setJavaScriptEnabled(true);
WebHistory history = webEngine.getHistory();
HistoryButton.setOnAction(e -> primaryStage.setScene(scene2));
BookmarksButton.setOnAction(e -> primaryStage.setScene(scene3));
RefreshButton.setOnAction(e -> webEngine.reload());
BackButton.setOnAction(e -> webEngine.executeScript("history.back()"));
BackToBrowser.setOnAction(e -> primaryStage.setScene(scene));
ForwardButton.setOnAction(e -> webEngine.executeScript("history.forward()"));
tf.setOnKeyPressed((KeyEvent ke) -> {
KeyCode key = ke.getCode();
if(key == KeyCode.ENTER){
webEngine.load("http://" + tf.getText());
}
});
sp.getChildren().addAll(HistoryButton, BookmarksButton, RefreshButton, BackButton, ForwardButton);
sp2.getChildren().addAll(BookmarksButton, BackToBrowser);
sp3.getChildren().addAll(HistoryButton, BackToBrowser);
ap.setRight(sp);
ap2.setRight(sp2);
ap3.setRight(sp3);
ap.setTop(tf);
ap.setCenter(browser);
browser.setPrefSize(700, 700);
primaryStage.setTitle("JTG Browser Alpha");
primaryStage.setScene(scene);
primaryStage.show();
}
}
See the node documentation:
If a program adds a child node to a Parent (including Group, Region, etc) and that node is already a child of a different Parent or the root of a Scene, the node is automatically (and silently) removed from its former parent.
You are adding your HistoryButton (and other buttons) to different scenes and, when you do so, they are automatically removed from the previous scenes. You need to create new button instances if you want them visible in every scene.
Small aside: it is best to follow Java naming conventions, e.g. historyButton instead of HistoryButton.

JavaFX Stage wont show in Android

I have deployed a JavaFX application in Android using Gluon Plugin. What Im trying to do right now is to show a second Stage, but unfortunately it wont show.
Here's the code of the second Stage:
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Setting {
public Setting(){
Text title = new Text("Settings");
title.setId("setting-title");
title.setFont(Font.font("Arial", (int)(MainApp.HEIGHT * 0.04)));
Label label_url = new Label("URL");
label_url.setFont(Font.font("Arial", (int)(MainApp.HEIGHT * 0.03)));
Label label_style = new Label("Style");
label_style.setFont(Font.font("Arial", (int)(MainApp.HEIGHT * 0.03)));
TextField text_url = new TextField(MainApp.URL);
text_url.setFont(Font.font("Arial", (int)(MainApp.HEIGHT * 0.03)));
ComboBox style_box = new ComboBox();
style_box.setStyle("-fx-font-size:"+(int)(MainApp.HEIGHT * 0.03)+"px;");
ObservableList<String> data = FXCollections.observableArrayList();
data.add("Blue");
data.add("Red");
data.add("Yellow");
style_box.setItems(data);
GridPane grid = new GridPane();
grid.setVgap(5);
grid.setHgap(5);
grid.add(label_url, 0, 0);
grid.add(label_style, 0, 1);
grid.add(text_url, 1, 0);
grid.add(style_box, 1, 1);
VBox root = new VBox();
root.setAlignment(Pos.CENTER);
root.getChildren().addAll(title,grid);
Scene scene = new Scene(root, MainApp.WIDTH * 0.6, MainApp.HEIGHT * 0.4);
if(MainApp.SETTING == null){
MainApp.SETTING = new Stage();
MainApp.SETTING.setScene(scene);
MainApp.SETTING.initOwner(MainApp.MAINSTAGE);
MainApp.SETTING.setTitle("Settings");
}
}
public void show(){
if(!MainApp.SETTING.isShowing()) MainApp.SETTING.show();
}
}
This code works when I tried to run it as a desktop application. Im using Android 4.2.
Using JavaFXPorts you can change scenes and stages while running on Android.
I've modified the Gluon plugin for NetBeans default sample to achieve this, first switching scenes:
private Scene mainScene;
#Override
public void start(Stage stage) {
Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
Label label = new Label("Main Scene");
StackPane root = new StackPane(label);
mainScene = new Scene(root, visualBounds.getWidth(), visualBounds.getHeight());
stage.setScene(mainScene);
stage.show();
label.setOnMouseClicked(e->{
Label labelSettings = new Label("Settings Scene. Click to go back");
StackPane rootSettings = new StackPane(labelSettings);
Scene settingsScene = new Scene(rootSettings, visualBounds.getWidth(), visualBounds.getHeight());
stage.setScene(settingsScene);
labelSettings.setOnMouseClicked(t->stage.setScene(mainScene));
});
}
Now switching stages:
private Scene mainScene;
#Override
public void start(Stage stage) {
Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
Label label = new Label("Main Stage");
StackPane root = new StackPane(label);
root.setStyle("-fx-background-color: aquamarine;");
mainScene = new Scene(root, visualBounds.getWidth(), visualBounds.getHeight());
stage.setScene(mainScene);
stage.setTitle("Main Stage");
stage.show();
label.setOnMouseClicked(e->{
Label labelSettings = new Label("Settings Stage. Click to go back");
StackPane rootSettings = new StackPane(labelSettings);
rootSettings.setStyle("-fx-background-color: burlywood;");
Scene settingsScene = new Scene(rootSettings, visualBounds.getWidth(), visualBounds.getHeight());
Stage stage2 = new Stage();
stage2.setScene(settingsScene);
stage2.show();
labelSettings.setOnMouseClicked(t->stage2.hide());
});
}
And there's another possibility: you can use Gluon Charm, to manage different views.
Have a look at this project to get you started.

Categories

Resources