How to bind in JavaFx a textField with others textFields. For Example
textFieldTotal.textProperty.bind(Bindings.multiply(textFieldAmount.textProperty,
textFieldPrice.textProperty));
You question is pretty vague, but I'm going to take a guess. Basically, you need to create some additional Property and Binding objects.
First, create properties for your two TextField nodes. Then, you'll bind them using a StringConverter to convert the text entered into doubles.
Finally, create a "total" property that multiplies the two fields together and displays them in a Label.
Here's a very simple application to test out:
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.StringConverter;
import javafx.util.converter.DoubleStringConverter;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
// Simple Interface
VBox root = new VBox(10);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(10));
// Quantity
HBox hBoxQuantity = new HBox(5);
hBoxQuantity.setAlignment(Pos.CENTER);
TextField txtQuantity = new TextField();
hBoxQuantity.getChildren().addAll(
new Label("Quantity:"),
txtQuantity
);
// Price
HBox hBoxPrice = new HBox(5);
hBoxPrice.setAlignment(Pos.CENTER);
TextField txtPrice = new TextField();
hBoxPrice.getChildren().addAll(
new Label("Price:"),
txtPrice
);
// Total
HBox hBoxTotal = new HBox(5);
hBoxTotal.setAlignment(Pos.CENTER);
Label lblTotal = new Label();
hBoxTotal.getChildren().addAll(
new Label("Total: $"),
lblTotal
);
// Properties used for bindings
DoubleProperty price = new SimpleDoubleProperty();
DoubleProperty quantity = new SimpleDoubleProperty();
DoubleProperty total = new SimpleDoubleProperty();
// Bind the total to price x quantity
total.bind(price.multiply(quantity));
// Setup the converters to get the input from the textfields
StringConverter<? extends Number> converter = new DoubleStringConverter();
// Bind the text field entries to their properties
Bindings.bindBidirectional(txtPrice.textProperty(), price, (StringConverter<Number>) converter);
Bindings.bindBidirectional(txtQuantity.textProperty(), quantity, (StringConverter<Number>) converter);
// Bind the total label
lblTotal.textProperty().bind(total.asString());
// Add all nodes to stage
root.getChildren().addAll(hBoxPrice, hBoxQuantity, hBoxTotal);
// Show the stage
primaryStage.setWidth(300);
primaryStage.setHeight(300);
primaryStage.setScene(new Scene(root));
primaryStage.setTitle("Sample");
primaryStage.show();
}
}
The Result:
Is this what you had in mind?
Note: This obviously does not include any error checking or restrictions on input, so you'll receive an error message if entering a non-numeric String in either TextField.
Related
I am trying to figure out how to make my VBox, only go to the size of 300 pixel's wide, but i would like to have it at say 250 pixels wide when the program is initialized, then when the user clicks full screen, I want it to expand, but not necessarily with the entire space it would have. I want it to only go to 300 pixels (and have the 3 buttons inside do the same thing) but I'm not sure how to do that. I'm having trouble determining PrefSize and CompSize actual meanings and uses. Any help would be great.
I am also having kind of the same problem with the Label, inside the HBox, that is inside a SplitPane, that is inside a BorderPane. Any explanation of why what you are suggesting will work, will help me with future problems like this. Thank you
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class MainStarUI extends Application {
#Override
public void start(Stage primaryStage){
MenuBar mainMenuOne = addMenuBar();
VBox leftVBoxOne = addVbox();
//AnchorPane midPaneOne = addAnchorPane();
//HBox topHBoxOne = addHBox();
SplitPane midSplitPane = addSplitPane();
BorderPane mainPane = new BorderPane();
mainPane.setTop(mainMenuOne);
mainPane.setLeft(leftVBoxOne);
mainPane.setCenter(midSplitPane);
primaryStage.setMinWidth(1440);
primaryStage.setMinHeight(900);
Scene mainScene = new Scene(mainPane);
primaryStage.setScene(mainScene);
primaryStage.show();
}
public MenuBar addMenuBar(){
Menu menuOne = new Menu("File");
Menu menuTwo = new Menu("Edit");
Menu menuThree = new Menu("Help");
Menu menuFour = new Menu("Exit");
MenuItem menuItemOne = new MenuItem("File");
MenuItem menuItemTwo = new MenuItem("Open");
MenuItem menuItemThree = new MenuItem("Exit");
menuOne.getItems().add(menuItemOne);
menuOne.getItems().add(menuItemTwo);
menuFour.getItems().add(menuItemThree);
MenuBar mainMenuOne = new MenuBar();
mainMenuOne.getMenus().add(menuOne);
mainMenuOne.getMenus().add(menuTwo);
mainMenuOne.getMenus().add(menuThree);
mainMenuOne.getMenus().add(menuFour);
mainMenuOne.maxHeight(25);
mainMenuOne.minHeight(25);
return mainMenuOne;
}
public VBox addVbox(){
VBox leftVBox = new VBox();
leftVBox.setMinWidth(300);
leftVBox.setPrefWidth(300);
leftVBox.setPadding(new Insets(15));
leftVBox.setSpacing(20);
leftVBox.setStyle("-fx-background-color: #336699;");
Button firstButton = new Button("Ships, Components, Items & Weaponry");
firstButton.setMinSize(270, 270);
firstButton.setMaxSize(270, 270);
Button secondButton = new Button("Trading, Mining, Refining & Commodities");
secondButton.setMinSize(270, 270);
secondButton.setMaxSize(270,270);
Button thirdButton = new Button("Star Systems, Planets, Moons & Locations");
thirdButton.setMinSize(270,270);
thirdButton.setMaxSize(270, 270);
leftVBox.getChildren().addAll(firstButton, secondButton, thirdButton);
return leftVBox;
}
public HBox addHBox(){
Image logoImage = new Image("SCImages/TaktikalLogo1.jpg");
ImageView logoImageView = new ImageView();
logoImageView.setImage(logoImage);
logoImageView.setPreserveRatio(false);
logoImageView.setFitWidth(160);
logoImageView.setFitHeight(160);
logoImageView.setSmooth(true);
logoImageView.setCache(true);
Label topLabel = new Label("STAR CITIZEN INFONET & DATABASE");
topLabel.setFont(new Font("Arial", 48));
topLabel.setTextFill(Color.WHITE);
topLabel.setMinHeight(160);
topLabel.setMaxHeight(160);
HBox topHBox = new HBox();
topHBox.setStyle("-fx-background-color: black");
topHBox.setMinHeight(180);
topHBox.setMaxHeight(180);
topHBox.setPrefWidth(1090);
topHBox.getChildren().addAll(logoImageView, topLabel);
topHBox.setPadding(new Insets(10));
topHBox.setSpacing(10);
return topHBox;
}
public SplitPane addSplitPane(){
HBox topHBoxOne = addHBox();
AnchorPane anchorSplitPane = new AnchorPane();
SplitPane mainSplitPane = new SplitPane();
mainSplitPane.setOrientation(Orientation.VERTICAL);
mainSplitPane.setDividerPosition(1, 200);
mainSplitPane.setPrefSize(1090, 850);
mainSplitPane.getItems().addAll(topHBoxOne, anchorSplitPane);
return mainSplitPane;
}
public static void main(String[] args) {
launch(args);
}
}
I actually put my VBox inside an AnchorPane, and attached it to the anchors, and everything worked perfectly after I set my preferred height and width.
here is my code
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
public class Main extends Application
{
private BorderPane root;
TreeView<String> tree;
#Override
public void start(Stage primaryStage) throws Exception
{
root = new BorderPane();
root.setLeft(getLeftHBox());
Scene scene = new Scene(root, 900, 500);
primaryStage.setTitle("JavaFx");
primaryStage.setScene(scene);
primaryStage.show();
}
private HBox getLeftHBox()
{
HBox hbox = new HBox();
Text text= new Text("Fall tree");
text.setFont(Font.font("Helvetica", FontWeight.BOLD,16));
VBox vbox =new VBox(10);
vbox.setPadding(new Insets(10));
TreeItem<String> Library,module,unite,translateA ,translateB,rotate;
//Root
Library = new TreeItem<>();
Library.setExpanded(true);
//module-Child of Root
module = makeBranch("module",Library);
makeBranch("Parameter X",module);
makeBranch("Parameter y",module);
//Unite-Child of module
unite = makeBranch("unite",module);
makeBranch("Parameter uX",unite);
makeBranch("Parameter uy",unite);
//TranslateA-Child of Unite
translateA = makeBranch("translateA",unite);
makeBranch("Parameter taX",translateA);
makeBranch("Parameter tay",translateA);
//TranslateB-Sibling of TranslateA
translateB = makeBranch("translateB",unite);
makeBranch("Parameter tbX",translateB);
makeBranch("Parameter tby",translateB);
//Rotate-Child of TranslateB
rotate = makeBranch("rotate",translateB);
makeBranch("Parameter RX",rotate);
makeBranch("Parameter RY",rotate);
tree= new TreeView<>(Library);
tree.setShowRoot(false);
vbox.getChildren().addAll(text,tree);
hbox.getChildren().addAll(vbox);
return hbox;
}
private TreeItem<String> makeBranch(String title, TreeItem<String> parent) {
TreeItem<String>item = new TreeItem<>(title);
item.setExpanded(true);
parent.getChildren().add(item);
return item;
}
public static void main(String[] args)
{
Application.launch(args);
}
}
in the output i got the fall tree/drop down menu. my question is how to edit the names in output. how can i give new titles/names to branches in output and that appear in my code.
Example: when you execute program, i have a branch name "module" on top of output. i want to change that name and write "Rotate_Module" in output.
(i can simply change the code to do that but i want to change it in output and that should automatically appear in my code)
Note# i want to change every name. thank you
To make the tree editable, which is what I think you mean in this question, you need to specify that you want the tree to use cells which incorporate a text field. You can do this with:
tree.setEditable(true);
tree.setCellFactory(TextFieldTreeCell.forTreeView());
If the user edits the tree and makes changes, then those changes will be stored in the TreeItem's valueProperty(); i.e. you can retrieve the values with module.getValue(), etc.
So to make the user's changes persistent, you will need to retrieve all those values and save them to a file (or database, or some other kind of persistent storage) when the application closes. To use those values, when you start the application, read the values from the file (or database, etc) and use those values when you create the tree items.
I was wondering if there is a way to display some text (like a info) under the buttons of a Dialog ? I've looked in many places, but even to align the buttons seems messy (from this post).
This is what I got for now. I just want the "Set my choice ..." text under the 2 buttons.
I looked for a function in the documentation that could help me display the way I want (like "getButtonBar()" or something like that) with no chance. Also creating a new ButtonBar seems a bit complicated for what I want to achieve.
I also tried to create a stage that could look like a dialog, but I needed the result incoming from clicking "Yes / No" in the same way the Dialogs do.
Is there any way to achieve want I want ? Or do I have to build it completely myself ? Thanks !
Just override the createButtonBar() method of DialogPane:
DialogPane pane = new DialogPane() {
#Override
public Node createButtonBar() {
VBox vbox = new VBox(5);
vbox.setAlignment(Pos.BOTTOM_RIGHT);
vbox.setPadding(new Insets(5));
vbox.getChildren().add(super.createButtonBar());
vbox.getChildren().add(new Label("Additional text"));
return vbox ;
}
};
Here's a SSCCE:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Dialog;
import javafx.scene.control.DialogPane;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class CustomDialogPaneTest extends Application {
#Override
public void start(Stage primaryStage) {
Button button = new Button("Show Dialog");
button.setOnAction(e -> {
DialogPane pane = new DialogPane() {
#Override
public Node createButtonBar() {
VBox vbox = new VBox(5);
vbox.setAlignment(Pos.BOTTOM_RIGHT);
vbox.setPadding(new Insets(5));
vbox.getChildren().add(super.createButtonBar());
vbox.getChildren().add(new Label("Additional text"));
return vbox ;
}
};
CheckBox checkBox = new CheckBox("A check box");
pane.setContent(checkBox);
pane.setHeaderText("The header");
pane.getButtonTypes().addAll(ButtonType.YES, ButtonType.NO);
Dialog<ButtonType> dialog = new Dialog<>();
dialog.setDialogPane(pane);
dialog.showAndWait().ifPresent(System.out::println);
});
StackPane root = new StackPane(button);
root.setPadding(new Insets(20));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I'm currently working on a project requiring me to switch back and forward between scenes. I have already written some code for it but it isn't as elegant as I wanted to be, especially as there is few flickers when I switch between them and sometimes even the buttons that I have generated simply disappear only to appear once again when yet another scene has been generated. Moreover, the layout I'm using for my application isn't really fixed and I think that using FXML might be not suitable for what I'm doing.
Thank you.
This is what I'm using to change between scenes:
void changeScene(Stage stage,Scene scene){
stage.setScene(scene);
primaryStage.setFullScreen(true);
}
I assume by "switching between scenes" you mean that you want to change the entire content of the existing window.
There are two (very) slightly different ways you can do this. Either create a new Scene and pass it to the Stage's setScene(...) method. Or create the Parent that is the root of the new UI (either by FXML or otherwise), and pass it to the existing Scene's setRoot(...) method. There's no real advantage that I can see of one over the other.
Here's a minimal implementation of the second option. The UI is irrelevant to the question: the important parts are the event handlers for the "Login" button (which switches from the login scene to the main scene) and the "Logout" button (which switches back).
import java.util.stream.IntStream;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;
public class MinimalSceneSwitchingExample extends Application {
#Override
public void start(Stage primaryStage) {
LoginView loginView = new LoginView();
Scene scene = new Scene(loginView.getView(), 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static class LoginView {
private final IntegerProperty loginAttempts ;
private final GridPane view ;
public LoginView() {
view = new GridPane();
TextField usernameTF = new TextField("user");
TextField passwordTF = new TextField("pass");
// Login button switches to main view:
Button loginButton = new Button("Login");
loginButton.setOnAction(event -> {
if (usernameTF.getText().equalsIgnoreCase("user")
&& passwordTF.getText().equalsIgnoreCase("pass")) {
// *** Switch to main view: ***
Parent mainView = new MainView().getView();
view.getScene().setRoot(mainView);
} else {
loginAttempts.set(loginAttempts.get()+1);
}
});
// just set up login UI... irrelevant to this example:
loginAttempts = new SimpleIntegerProperty();
usernameTF.setPromptText("Hint: user");
passwordTF.setPromptText("Hint: pass");
view.addRow(0, new Label("Username:"), usernameTF);
view.addRow(1, new Label("Password:"), passwordTF);
Label loginErrorMessage = new Label();
loginErrorMessage.textProperty().bind(
Bindings.when(loginAttempts.isEqualTo(0))
.then("")
.otherwise(Bindings.format("Login incorrect (Attempts: %d)",
loginAttempts)));
view.add(loginErrorMessage, 0, 2, 2, 1);
view.add(loginButton, 0, 3, 2, 1);
ColumnConstraints leftCol = new ColumnConstraints();
leftCol.setHgrow(Priority.NEVER);
leftCol.setHalignment(HPos.RIGHT);
ColumnConstraints rightCol = new ColumnConstraints();
rightCol.setHgrow(Priority.ALWAYS);
rightCol.setHalignment(HPos.LEFT);
view.getColumnConstraints().addAll(leftCol, rightCol);
GridPane.setHalignment(loginErrorMessage, HPos.CENTER);
GridPane.setHalignment(loginButton, HPos.CENTER);
view.setHgap(10);
view.setVgap(16);
view.setAlignment(Pos.CENTER);
}
public Parent getView() {
return view ;
}
}
public static class MainView {
private BorderPane view ;
public MainView() {
view = new BorderPane();
// *** logout button switches back to a login view: ***
Button logoutButton = new Button("Log out");
logoutButton.setOnAction(event ->
view.getScene().setRoot(new LoginView().getView()));
// Arbitrary UI, irrelevant to this example:
SplitPane splitPane = new SplitPane();
ListView<String> listView = new ListView<>();
IntStream.rangeClosed(1, 10)
.mapToObj(Integer::toString)
.map("Item "::concat)
.forEach(listView.getItems()::add);
Label bigLabel = new Label();
bigLabel.textProperty().bind(
listView.getSelectionModel().selectedItemProperty());
bigLabel.setFont(Font.font("Verdana", FontWeight.BOLD, 18));
BorderPane.setAlignment(bigLabel, Pos.CENTER);
BorderPane.setMargin(bigLabel, new Insets(10));
Label details = new Label();
details.textProperty().bind(
Bindings.when(
listView.getSelectionModel().selectedItemProperty().isNull())
.then("")
.otherwise(Bindings.format("This is where you would display "
+ "all sorts of details about %1$s. "
+ "If %1$s were really a model object, you "
+ "might have a GridPane displaying all its "
+ "properties, for example.",
listView.getSelectionModel().selectedItemProperty())));
details.setWrapText(true);
BorderPane detailsPane = new BorderPane(details, bigLabel, null, null, null);
splitPane.getItems().addAll(listView, detailsPane);
view.setCenter(splitPane);
view.setBottom(logoutButton);
BorderPane.setAlignment(logoutButton, Pos.CENTER);
BorderPane.setMargin(logoutButton, new Insets(8));
BorderPane.setMargin(splitPane, new Insets(16));
}
public Parent getView() {
return view ;
}
}
public static void main(String[] args) {
launch(args);
}
}
I have the majority of the program done, the only problem is getting the numbers to display in the TextArea. Write a program that lets the user enter numbers from a graphical user interface and displays them in a text area. Use a LinkedList to store the numbers. Don't duplicate numbers. Add sort, shuffle, reverse to sort the list.
package storedInLinkedList;
import java.util.Collections;
import java.util.LinkedList;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.control.ScrollPane;
public class StoredInLinkedList extends Application{
TextField txt = new TextField();
TextArea tArea = new TextArea();
Label message = new Label("Enter a Number: ");
Button sort = new Button("Sort");
Button shuffle = new Button("Shuffle");
Button reverse = new Button("Reverse");
private LinkedList<Integer> list = new LinkedList<>();
#Override
public void start(Stage primaryStage){
BorderPane bPane = new BorderPane();
txt.setAlignment(Pos.TOP_RIGHT);
bPane.setCenter(txt);
bPane.setBottom(tArea);
HBox hBox = new HBox(message, txt);
bPane.setTop(hBox);
HBox buttons = new HBox(10);
buttons.getChildren().addAll(sort, shuffle, reverse);
bPane.setBottom(buttons);
buttons.setAlignment(Pos.CENTER);
VBox vBox = new VBox();
vBox.getChildren().addAll(hBox, tArea, buttons);
bPane.setCenter(new ScrollPane(tArea));
Scene scene = new Scene(vBox, 300,250);
primaryStage.setTitle("20.2_DSemmes");
primaryStage.setScene(scene);
primaryStage.show();
txt.setOnAction(e -> {
if(! list.contains(new Integer(txt.getText()))){
tArea.appendText(txt.getText() + " ");
list.add(new Integer(txt.getText()));
}//end if
});//end action
sort.setOnAction(e -> {
Collections.sort(list);
display();
});//end action
shuffle.setOnAction(e -> {
Collections.shuffle(list);
display();
});//end action
reverse.setOnAction(e -> {
Collections.reverse(list);
display();
});//end action
}//end stage
private void display() {
for (Integer i: list){
tArea.setText(null);
tArea.appendText(i + " ");
}//end for
}//end display
public static void main(String[] args) {
// TODO Auto-generated method stub
launch(args);
}//end main
}//end class
Put the textarea clearing code outside of for loop. Otherwise you are clearing the previously appended text, so textarea having only the last element of list:
private void display() {
tArea.setText(""); // clear text area
for (Integer i: list){
tArea.appendText(i + " ");
}//end for
}/