Creating multiple text fields in javafx - javafx

Is there anyway I can do a for loop to create multiple textfields. Say I want like 20 text fields...do I have to create them individually?

It's not really clear what your question is. Just write a for loop and create each TextField inside it.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TwentyTextFields extends Application {
#Override
public void start(Stage primaryStage) {
final int numTextFields = 20 ;
TextField[] textFields = new TextField[numTextFields];
VBox root = new VBox(5);
for (int i = 1; i <= numTextFields; i++) {
TextField tf = new TextField();
String name = "Text field "+i ;
tf.setOnAction(e -> {
System.out.println("Action on "+name+": text is "+tf.getText());
});
root.getChildren().add(tf);
textFields[i-1] = tf ;
}
Scene scene = new Scene(new ScrollPane(root), 250, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Related

How to create table with vertical/column header in JavaFX

Is there a way to create tableview with vertical headings ? I don't see any option in javafx to do this.
You can set the graphic to a Label which is rotated, and set the text to an empty string.
private void makeColumnHeader(TableColumn<?,?> column) {
Label label = new Label();
label.setText(column.getText());
column.setText("");
label.setRotate(90);
column.setGraphic(label);
}
Here's a complete example:
import javafx.application.Application;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.fxml.FXMLLoader;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import java.io.IOException;
public class HelloApplication extends Application {
private void makeColumnHeader(TableColumn<?,?> column) {
Label label = new Label();
label.setText(column.getText());
column.setText("");
label.setRotate(90);
column.setGraphic(label);
}
#Override
public void start(Stage stage) throws IOException {
TableView<Item> table = new TableView<>();
TableColumn<Item, Number> idColumn = new TableColumn<>("Id");
idColumn.setCellValueFactory(data -> new SimpleIntegerProperty(data.getValue().id()));
TableColumn<Item, String> itemColumn = new TableColumn<>("Item");
itemColumn.setCellValueFactory(data -> new SimpleStringProperty(data.getValue().name()));
makeColumnHeader(idColumn);
makeColumnHeader(itemColumn);
table.getColumns().add(idColumn);
table.getColumns().add(itemColumn);
for (int i = 1 ; i <= 20; i++) table.getItems().add(new Item(i, "Item "+i));
BorderPane root = new BorderPane(table);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static record Item(int id, String name){}
public static void main(String[] args) {
launch();
}
}
Note that setting the column's text to an empty string can have undesirable side effects. For example, the tableMenuButton relies on the text in the table columns to display the menu items. Add table.setTableMenuButtonVisible(true); to the code above to see the problem.
A slightly more robust solution is to bind the text of the label in the graphic to the text in the column, and then use CSS to hide the default text:
private void makeColumnHeader(TableColumn<?,?> column) {
Label label = new Label();
label.textProperty().bind(column.textProperty());
label.setRotate(90);
column.setGraphic(label);
}
and in an external style sheet:
.table-column > .label {
-fx-content-display: graphic-only;
}
I had to adapt the solution from #James_D to properly size the label by applying a minWidth and wrapping it in a Group: (Tested with openjfx19)
private void makeColumnHeader(TableColumn<?, ?> column, String text) {
Label label = new Label();
label.setText(text);
label.setRotate(-90);
label.setMinWidth(80);
column.setGraphic(new Group(label));
column.getStyleClass().add("rotated");
}

How do I show contents from the password field in javafx using checkbox [duplicate]

This question already has answers here:
How to unmask a JavaFX PasswordField or properly mask a TextField?
(7 answers)
Closed 3 years ago.
Im a student studying java and javafx, how do I show the password in the passwordfield using a checkbox? I am using gluon scenebuilder as my fxml editor
The duplicate is listed above for the correct but more complicated way of doing this. In this answer, I am showing two examples. One with a CheckBox and the other with the all-seeing eye. The eye is to use a StackPane to layer the node. For the CheckBox solution, put a TextField and then a PasswordField in the StackPane. Bring the TextField toFront when the CheckBox is checked and set its text using the PasswordField. Clear the TextField when the CheckBox is not checked and move the PasswordField toFront. For the All-seeing eye example, use the same ideas but add an ImageView and always keep the ImageView toFront.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TestingGround extends Application
{
Image image = new Image("https://previews.123rf.com/images/andrerosi/andrerosi1905/andrerosi190500216/123158287-eye-icon-vector-look-and-vision-icon-eye-vector-icon.jpg");
#Override
public void start(Stage primaryStage)
{
HBox passwordControl1 = createPasswordFieldWithCheckBox();
HBox passwordControl2 = createPasswordFieldWithCheckBox();
StackPane passwordControl3 = createPasswordFieldWithEye();
StackPane passwordControl4 = createPasswordFieldWithEye();
VBox root = new VBox(passwordControl1, passwordControl2, passwordControl3, passwordControl4);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
HBox createPasswordFieldWithCheckBox()
{
PasswordField passwordField = new PasswordField();
passwordField.setPrefHeight(50);
TextField textField = new TextField();
textField.setPrefHeight(50);
passwordField.textProperty().bindBidirectional(textField.textProperty());
StackPane stackPane = new StackPane(textField, passwordField);
CheckBox checkBox = new CheckBox();
checkBox.selectedProperty().addListener((observable, oldValue, newValue) -> {
if (newValue) {
textField.toFront();
}
else {
passwordField.toFront();
}
});
HBox root = new HBox(stackPane, checkBox);
root.setSpacing(5);
root.setAlignment(Pos.CENTER);
return root;
}
StackPane createPasswordFieldWithEye()
{
PasswordField passwordField = new PasswordField();
passwordField.setPrefHeight(50);
TextField textField = new TextField();
passwordField.textProperty().bindBidirectional(textField.textProperty());
textField.setPrefHeight(50);
ImageView imageView = new ImageView(image);
imageView.setFitHeight(32);
imageView.setFitWidth(32);
StackPane.setMargin(imageView, new Insets(0, 10, 0, 0));
StackPane.setAlignment(imageView, Pos.CENTER_RIGHT);
imageView.setOnMousePressed((event) -> {
textField.toFront();
imageView.toFront();
});
imageView.setOnMouseReleased((event) -> {
passwordField.toFront();
imageView.toFront();
});
StackPane root = new StackPane(textField, passwordField, imageView);
return root;
}
}
You could use a custom Tooltip to show the password:
import javafx.application.Application;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.geometry.Insets;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class FxMain extends Application {
private SimpleBooleanProperty showPassword ;
private CheckBox checkBox;
private Tooltip toolTip;
private PasswordField pF;
private Stage stage;
#Override
public void start(Stage stage) {
this.stage = stage;
showPassword = new SimpleBooleanProperty();
showPassword.addListener((ChangeListener<Boolean>) (observable, oldValue, newValue) -> {
if(newValue){
showPassword();
}else{
hidePassword();
}
});
final Label message = new Label("");
Label label = new Label("Password");
toolTip = new Tooltip();
toolTip.setShowDelay(Duration.ZERO);
toolTip.setAutoHide(false);
toolTip.setMinWidth(50);
pF = new PasswordField();
pF.setOnKeyTyped(e -> {
if ( showPassword.get() ) {
showPassword();
}
});
HBox hb = new HBox(10, label, pF);
hb.setAlignment(Pos.CENTER_LEFT);
checkBox = new CheckBox("Show password");
showPassword.bind(checkBox.selectedProperty());
VBox vb = new VBox(10, hb, checkBox, message);
vb.setPadding(new Insets(10));
stage.setScene(new Scene(vb,300,100));
stage.show();
}
private void showPassword(){
Point2D p = pF.localToScene(pF.getBoundsInLocal().getMaxX(), pF.getBoundsInLocal().getMaxY());
toolTip.setText(pF.getText());
toolTip.show(pF,
p.getX() + stage.getScene().getX() + stage.getX(),
p.getY() + stage.getScene().getY() + stage.getY());
}
private void hidePassword(){
toolTip.setText("");
toolTip.hide();
}
public static void main(String[] args) {
launch(args);
}
}

Javafx: get a Scrollbar from a Treeview at a Button Event

I want to create a button event to create a list. On this list, the Scrollbar
should be moved. But I become an error because the lookup method is only usable after rendering.
HBox root = new HBox();
Button b = new Button("initList");
b.setOnAction(e->
{
ListView<String> list = new ListView<String>();
for (int i = 0; i < 20; i++)
{
list.getItems().add(i+"");
}
ScrollBar bar = (ScrollBar) list.lookup(".scroll-bar");
bar.setValue(0.5);
root.getChildren().add(list);
});
root.getChildren().add(b);
Scene scene = new Scene(root,400,400);
primaryStage.setScene(scene);
primaryStage.show();
To ensure to be called after the layout, you can queue the task using runLater:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.ScrollBar;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class LookupTest extends Application {
#Override
public void start(Stage primaryStage) {
HBox root = new HBox();
Button b = new Button("initList");
b.setOnAction(e ->
{
ListView<String> list = new ListView<String>();
for (int i = 0; i < 20; i++) {
list.getItems().add(i + "");
}
Platform.runLater(() -> {
ScrollBar bar = (ScrollBar) list.lookup(".scroll-bar");
if (bar != null) bar.setValue(0.5);
});
root.getChildren().add(list);
});
root.getChildren().add(b);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

How to change images with Timeline in JavaFX

I intend to change the images of birds over the time by adding key frames in a for loop to the timeline object. It turns out that only the first image is displayed. Could someone point out where part I got it wrong. Thanks in advance.
Besides, I noticed that I have to reset the counter "index" to 0 after for loop otherwise it generates java.lang.ArrayIndexOutOfBoundsException.
package application;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.util.Duration;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.effect.BoxBlur;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
public class Main extends Application
{
int index=0;
#Override
public void start(Stage primaryStage) {
try {
ImageView bgV = new ImageView();
Image img_BG = new Image(Main.class.getResourceAsStream("background.png"));
bgV.setImage(img_BG);
bgV.setEffect(new BoxBlur());
bgV.setOpacity(0.5);
ImageView t1V = new ImageView();
Image img_t1 = new Image(Main.class.getResourceAsStream(
"t1.png"
));
t1V.setImage(img_t1);
ImageView t2V = new ImageView();
Image img_t2 = new Image(Main.class.getResourceAsStream(
"t2.png"
));
t2V.setImage(img_t2);
ImageView t3V = new ImageView();
Image img_t3 = new Image(Main.class.getResourceAsStream(
"t3.png"
));
t3V.setImage(img_t3);
Group foreground = new Group(t1V,t2V,t3V);
t1V.setTranslateX(20);
t1V.setTranslateY(200);
t2V.setTranslateX(300);
t2V.setTranslateY(200);
t3V.setTranslateX(550);
t3V.setTranslateY(200);
foreground.setEffect(new DropShadow());
String[]
birdFiles = {"b1.png", "b2.png", "b3.png", "b4.png", "b5.png", "b6.png"};
double[] ds = { 300, 600, 900, 1200, 1500, 1800};
ImageView birdV = new ImageView(new Image(Main.class.getResourceAsStream(birdFiles[0])));
Group birds = new Group(birdV);
birds.setTranslateX(img_BG.getWidth()-100);
Timeline timeline = new Timeline();
timeline.setCycleCount(
Animation.INDEFINITE
);
KeyFrame[] kframs = new KeyFrame[birdFiles.length];
for( index=0; index<birdFiles.length; index++)
{
EventHandler<ActionEvent>
onFishined = new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent arg0)
{
birds.getChildren().setAll(new ImageView(new Image(Main.class.getResourceAsStream(birdFiles[index]))));
}
};
Duration duration = Duration.millis(ds[index]);
KeyFrame
kf = new KeyFrame(duration, onFishined,null,null );
timeline.getKeyFrames().add(kf);
}//End for i
index = 0;
timeline.play();
Group root = new Group(bgV,foreground,birds);
Scene scene = new Scene(root,img_BG.getWidth(), img_BG.getHeight());
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
you don't have to declare your index-field outside. this also causes your problem: whenever the handle method is called, it will reference your field: index which you set to 0 after your loop.
therefor you can declare a new field as finaland pass it to the handler:
for (int index = 0; index < birdFiles.length; index++) {
final int birdIndex = index;
EventHandler<ActionEvent> onFishined = new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
birds.getChildren().setAll(new ImageView(new Image(Main.class.getResourceAsStream(birdFiles[birdIndex]))));
}
};
...
}

Add content in TitlePane

I want to add several TreeViews into TitlePana.
private static TitledPane pane = new TitledPane("Connections", null);
public static void initTree(String name)
{
pane.setContent(tree(name));
}
pane.setContent(<node>);
But when I add TreeView the new node always replaces the old one. Is this a design problem. Any idea is this a code problem?
Set the content of the titled pane to some layout pane, and then add the tree views to the layout pane.
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TitledPane;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TreesInATitledPane extends Application {
#Override
public void start(Stage primaryStage) {
final TitledPane titledPane = new TitledPane();
titledPane.setText("Trees");
final VBox forest = new VBox(5);
final int NUM_TREES = 4 ;
for (int i=1; i<= NUM_TREES; i++) {
forest.getChildren().add(createRandomTree("Tree "+i));
}
titledPane.setContent(forest);
final BorderPane root = new BorderPane();
root.setTop(titledPane);
final Scene scene = new Scene(root, 300, 600);
primaryStage.setTitle("Can't see the forest for the trees");
primaryStage.setScene(scene);
primaryStage.show();
}
public TreeView<String> createRandomTree(String prefix) {
final Random rng = new Random();
List<TreeItem<String>> nodes = new ArrayList<>();
TreeItem<String> root = new TreeItem<>(prefix + " Root");
root.setExpanded(true);
nodes.add(root);
for (int i=1 ; i < 15; i++) {
final TreeItem<String> treeItem = new TreeItem<>(prefix + " Item "+i);
treeItem.setExpanded(true);
nodes.get(rng.nextInt(i)).getChildren().add(treeItem);
nodes.add(treeItem);
}
TreeView<String> tree = new TreeView<>(root);
return tree ;
}
public static void main(String[] args) {
launch(args);
}
}

Resources