how to edit/change name in output in javafx - javafx

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.

Related

How to use modal dialog in this case?

I have a question. I need to make a GridPane with a directory choose that will then lead me to a modal dialog showing photos. I cannot figure how to do the modal dialog that also has to be a GridPane or a HBox...so the question is , how do I get to show a Modal Dialog after selecting the Folder and pressing the "Show" Button... Thanks a lot!
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;
public class FotoView extends Application {
#Override
public void start(Stage primaryStage) {
TextField tf = new TextField();
Button b1 = new Button("Search");
Button b2 = new Button("Show");
DirectoryChooser dc = new DirectoryChooser();
GridPane gp = new GridPane();
gp.add(tf, 0 , 0);
gp.add(b1, 1, 0);
gp.add(b2, 0, 1);
b1.setOnAction(e-> dc.showDialog(primaryStage));
primaryStage.setScene(new Scene(gp)) ;
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
} ```
Below is a quick example where a first window has a button that opens up a DirectoryChooser. Once a directory has been selected a second smaller window opens up with the Modality set to APPLICATION_MODAL. In this second window you could add the image(s) that you load and add them to the GridPane.
import java.io.File;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.DirectoryChooser;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(final String[] args) {
launch(args);
}
#Override
public void start(final Stage aStage) throws Exception {
final HBox root = new HBox();
final Button browseBtn = new Button("Click to open a Directory chooser");
root.getChildren().add(browseBtn);
browseBtn.setOnAction(e -> {
final DirectoryChooser chooser = new DirectoryChooser();
final File dir = chooser.showDialog(aStage);
openNewModalStage(aStage, dir);
});
final Scene scene = new Scene(root, 500, 500);
aStage.setScene(scene);
aStage.show();
}
private void openNewModalStage(final Stage aStage, final File aDirectory) {
final Stage stage = new Stage();
final GridPane grid = new GridPane();
final Scene scene = new Scene(grid);
grid.setStyle("-fx-background-color:black");
grid.setPrefWidth(400);
grid.setPrefHeight(400);
// get your images from 'aDirectory' and add them to your grid pane.
stage.setScene(scene);
// set the new windows Modality.
stage.initModality(Modality.APPLICATION_MODAL);
stage.show();
}
}
This way you would only need the one button and the dialog would show as soon as you've selected a directory. However, if you would still want a Search and Show button then just store the directory as a variable and add a listener on the 'show' button and move the openNewModalStage call to that one and remove the second argument.
Edit:
Also, depending on how many images and exactly what you want to display in the modal window, you might want to reconsider the GridPane and use a TilePane, or an hbox/vbox inside of a scroll pane. It's just a thought but I don't know what you will be doing with the GridPane.

JavaFX Slider : How to drag the thumb only by increments

I am trying to implement the Slider such that user can drag only by given increments. I tried in different ways by using the Slider API, but didnt get the desired results. Below is a quick demo of what I had tried. I am expecting to drag the thumb only in increments of 10 not with intermediate values. snapToTicks is doing what I required, but only after finishing the drag. I am trying to not move the thumb till the next desired block increment is reached.
Can anyone let me know how can i achieve this. Below is the screenshot while dragging.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class SliderDemo extends Application {
public static void main(String... args){
Application.launch(args);
}
#Override
public void start(Stage stage) throws Exception {
Label label = new Label();
label.setStyle("-fx-font-size:30px");
Slider slider = new Slider(5,240,5);
slider.setBlockIncrement(10);
slider.setMajorTickUnit(10);
slider.setMinorTickCount(0);
slider.setShowTickLabels(true);
slider.setShowTickMarks(true);
slider.setSnapToTicks(true);
slider.valueProperty().addListener((obs,old,val)->label.setText((int)Math.round(val.doubleValue())+""));
VBox root = new VBox(slider,label);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(20));
root.setSpacing(20);
Scene scene = new Scene(root,600,200);
stage.setScene(scene);
stage.show();
}
}
The solution is to set the value of the slider directly inside of the listener. The listener will not be called again
final ChangeListener<Number> numberChangeListener = (obs, old, val) -> {
final double roundedValue = Math.floor(val.doubleValue() / 10.0) * 10.0;
slider.valueProperty().set(roundedValue);
label.setText(Double.toString(roundedValue));
};
slider.valueProperty().addListener(numberChangeListener);
If you use Math.floor() instead of round you get a more intuatuive behavior of the thumb.

Bind textfield in JavaFX

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.

How to delete branching TreeItems from a TreeView in javafx?

How would I implement the method
private void wipeTreeViewStructure(TreeItem node)
where "node" is a TreeItem which, along with all of its connected TreeItems, gets erased on execution? I tried something along the lines of
private void wipeTreeViewStructure(TreeItem node) {
for (TreeItem i : node.getChildren()) {
wipeTreeViewStructure(i);
i.delete();
}
}
but that has two major flaws:
I'm getting an "Incompatible types" error in the "i", which I don't know what to make out of.
there is apparently no delete() or any similar method implemented for TreeItem.
With this many unknowns, I thought it would be better to just ask how it's done.
Your incompatible types error is (I think) because you are using raw types, instead of properly specifying the type of the object in the TreeItem. In other words, you should be using
TreeItem<Something>
instead of just the raw
TreeItem
The Something is whatever you are using as data in your tree. Your IDE should be giving you lots of warnings over this.
You don't need recursion at all here. To remove the tree item, just remove it from its parent's list of child nodes. It will effectively take all its descendents with it. You can do
node.getParent().getChildren().remove(node);
and that should do everything you need. (If the node might be the root of the tree, then you should check for that first.)
SSCCE:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class TreeViewWithDelete extends Application {
#Override
public void start(Stage primaryStage) {
TreeItem<String> treeRoot = new TreeItem<>("Root");
treeRoot.setExpanded(true);
TreeView<String> tree = new TreeView<>(treeRoot);
tree.getSelectionModel().select(treeRoot);
Button delete = new Button("Delete");
delete.setOnAction(e -> {
TreeItem<String> selected = tree.getSelectionModel().getSelectedItem();
selected.getParent().getChildren().remove(selected);
});
delete.disableProperty().bind(tree.getSelectionModel().selectedItemProperty().isNull()
.or(tree.getSelectionModel().selectedItemProperty().isEqualTo(treeRoot)));
TextField textField = new TextField();
Button add = new Button("Add");
EventHandler<ActionEvent> addAction = e -> {
TreeItem<String> selected = tree.getSelectionModel().getSelectedItem();
if (selected == null) {
selected = treeRoot ;
}
String text = textField.getText();
if (text.isEmpty()) {
text = "New Item";
}
TreeItem<String> newItem = new TreeItem<>(text);
selected.getChildren().add(newItem);
newItem.setExpanded(true);
tree.getSelectionModel().select(newItem);
};
textField.setOnAction(addAction);
add.setOnAction(addAction);
HBox controls = new HBox(5, textField, add, delete);
controls.setAlignment(Pos.CENTER);
controls.setPadding(new Insets(5));
BorderPane root = new BorderPane(tree, null, null, controls, null);
Scene scene = new Scene(root, 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

How can a dynamically generated JavaFX scene be changed in a single stage?

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

Resources