JavaFX updating ComboBox - java

I'm getting tons of Unknown Source errors when updating content in my ComboBox.
Here is how I assign data to the combobox
DateBox.setItems(FXCollections.observableArrayList(dateList));
DateBox.getSelectionModel().selectFirst();
Then I add changelistener with this line
DateBox.valueProperty().addListener((obs, oldVal, newVal) -> listListener(newVal));
Now when I update the dateList and call the first segment of code again it works if I don't have that listener set. But if I call it with the listener set it spews out Unknown Source. Most likely I could bypass this by removing the listener before I update and then adding it back in but I couldn't find any way to do it. Also that wouldn't most likely be the correct way to do it.
How could I update the ComboBox (DateBox) without it causing all of those errors to popup. I assume the problem is that I change the content with setItems. I'd guess there is a way to cause the combobox to update but I couldn't find it.

Here is a runnable example where one combo box updates the other
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.Arrays;
public class Main extends Application {
#Override
public void start(Stage stage) {
ArrayList<String> list = new ArrayList<>(Arrays.asList("1", "2", "3"));
ComboBox<String> comboBoxOne = new ComboBox<>();
ComboBox<String> comboBoxTwo = new ComboBox<>();
comboBoxOne.getItems().addAll(list);
comboBoxOne.setOnAction(event -> {
comboBoxTwo.getItems().clear();
ArrayList<String> listTwo = new ArrayList<>();
for (int i = 0; i < 5; i++)
listTwo.add(comboBoxOne.getValue());
comboBoxTwo.getItems().addAll(listTwo);
});
VBox vBox = new VBox(comboBoxOne, comboBoxTwo);
Scene scene = new Scene(vBox);
stage = new Stage();
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) { launch(args); }
}

Related

How to display some values of javafx combo box before any click on it?

I use a combo that works nice. The only thing i would like to add is to diplay some items(~10) of this box by default at start . I tried to find this property but a hell to find this among all methods.
If somebody knows how to to that
I have the same question for Menubutton
Thanks
Just call show() on the ComboBox. Here is an example:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class ComboTest extends Application {
#Override
public void start(Stage stage) {
ComboBox<String> combo = new ComboBox<>();
for (int i = 1 ; i <= 20 ; i++) combo.getItems().add("Item "+i);
BorderPane root = new BorderPane();
root.setTop(combo);
Scene scene = new Scene(root, 650, 400);
stage.setScene(scene);
stage.show();
combo.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
The same thing works for MenuButton.

How to define setOnAction for tableView rows?

I am writing a program with javafx and tableView feature.
My purpose is when I click on a row of this table,another window opens and shows something but I don't know how to define something like setOnMouseClicked feature for my table.
I searched a lot but I coudn't find a simple way
This is my existing code that define table columns and rows.(rows are defined with observable feature)
package sample;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
TableView tableView = new TableView();
TableColumn<String, Account> column1 = new TableColumn<>("UserName");
column1.setCellValueFactory(new PropertyValueFactory<>("userName"));
column1.setMinWidth(100);
TableColumn<String, Account> column2 = new TableColumn<>("PassWord");
column2.setCellValueFactory(new PropertyValueFactory<>("passWord"));
column2.setMinWidth(100);
tableView.getColumns().add(column1);
tableView.getColumns().add(column2);
tableView.setItems(getAllAccounts());
VBox vbox = new VBox(tableView);
Scene scene = new Scene(vbox,200,200);
Stage window ;
window = primaryStage;
window.setScene(scene);
window.show();
}
private ObservableList<Account> getAllAccounts(){
ObservableList<Account> accounts= FXCollections.observableArrayList(Account.getAccounts());
return accounts;
}
}
You actually have two options:
Method 1:
Implement a click listener on the TableView and retrieve the item that was selected.
// Listen for a mouse click and access the selectedItem property
tblAccounts.setOnMouseClicked(event -> {
// Make sure the user clicked on a populated item
if (tblAccounts.getSelectionModel().getSelectedItem() != null) {
System.out.println("You clicked on " + tblAccounts.getSelectionModel().getSelectedItem().getUsername());
}
});
Method 2:
Create your own RowFactory for the TableView and handle your logic there. (I prefer this method)
// Create a new RowFactory to handle actions
tblAccounts.setRowFactory(tv -> {
// Define our new TableRow
TableRow<Account> row = new TableRow<>();
row.setOnMouseClicked(event -> {
System.out.println("Do your stuff here!");
});
return row;
});
Method #1 is the simplest approach and will work for most needs. You'll want to use method #2 for more complex needs, such as styling the individual rows, or to handle clicks on empty rows.

Java FX update one TextField based on another TextField value

I am new to JAVA FX, I want to 'live' update one TextField based on another TextField value.
This is my snippet code:
#FXML
private void initialize() {
tf_code.textProperty().addListener((observable, oldValue, newValue) -> {
System.out.println(newValue.substring(2, 6));
tf_newCode.setText(newValue.substring(2, 6));
});
}
Should I add another listener to my second TextField ?
Works for me. Note that the below code does not require a .fxml file. Perhaps the call to method substring() in the code you posted is throwing an Exception that you are unaware of because you are catching it in an empty catch block? Of-course I'm only guessing since you only posted part of your code.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class JfxTst00 extends Application {
public void start(Stage mainStage) throws Exception {
mainStage.setTitle("JfxTst00");
BorderPane root = new BorderPane();
TextField tf_NewCode = new TextField();
TextField tf_Code = new TextField();
tf_Code.textProperty().addListener((observable, oldVal, newVal) -> tf_NewCode.setText(newVal));
root.setTop(tf_Code);
root.setBottom(tf_NewCode);
Scene scene = new Scene(root, 220, 70);
mainStage.setScene(scene);
mainStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Your questions does not actually explain the problem you're facing, though I see a few that you should be having.
First of all, you only need one listener for the first TextField because that is the one we are watching for changes.
Then you need to account for input into the TextField that is less than 2 characters and more than 6. Since you have set hard limits in your subString(2, 6) call, we only want our listener to work within those constraints.
Here is a simple text application that demonstrates:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TextFieldBinding extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
// Simple interface
VBox root = new VBox(5);
root.setPadding(new Insets(10));
root.setAlignment(Pos.CENTER);
TextField txt1 = new TextField();
TextField txt2 = new TextField();
txt1.textProperty().addListener((observable, oldValue, newValue) -> {
// First, only update txt2 if the new value entered in txt1 is greater than 2, otherwise
// our substring() method will throw an exception
if (newValue.length() > 2) {
// We also need to prevent trying to get a substring that exceeds the remaining length
// of the txt1 input
int maxIndex;
if (newValue.length() < 6) {
maxIndex = newValue.length();
} else {
maxIndex = 6;
}
// Now set the text for txt2
txt2.setText(newValue.substring(2, maxIndex));
}
});
root.getChildren().addAll(txt1, txt2);
// Show the Stage
primaryStage.setWidth(300);
primaryStage.setHeight(300);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}

JavaFX Textfield behind one character when grabbing text

This code below which is triggered by a typed key into a JavaFX textfield is always behind one character. For instance, if user types in k, the string printed for searchBar.getText() equals "". If a user types in another k it will equal "k", and so on.
//this is triggered when a key is typed into search bar
#FXML public void onKeyPressedOnSearch(){
File[] fileCollection = model.getFileCollection();
System.out.println(searchBar.getText());
System.out.println(fileCollection[0].getName().substring(0, searchBar.getText().length()));
List<String> list = new ArrayList<String>();
ObservableList<String> tempObservableList = FXCollections.observableList(list);
/* for(int i = 0; i < fileCollection.length; i++){
if(!(searchBar.getText().equals(fileCollection[i].getName().substring(0, searchBar.getText().length())))){
tempObservableList.remove(i);
}
}
if(searchBar.getText() == null || searchBar.getText() == ""){
songList.setItems(observableList);
}else{
songList.setItems(tempObservableList);
} */
}
I would suggest to add a ChangeListener to the TextField, so you can grab any change in it from there, Please consider this example:
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class CharByCharGrabbing extends Application {
#Override
public void start(Stage stage) throws Exception {
// create simple root and add two text fields to it
VBox root = new VBox();
root.setAlignment(Pos.CENTER);
// just styling
root.setBackground(new Background(new BackgroundFill(Color.MAGENTA, null,null)));
TextField textField = new TextField();
TextField textField1 = new TextField();
root.getChildren().addAll(textField, textField1);
Scene scene = new Scene(root, 300,200);
stage.setScene(scene);
stage.setTitle("Grabbing Char by Char");
stage.show();
// Now you can add a change listener to the text property of the text field
// it will keep you updated with every single change (char by char)
// either adding to or removing from the TextField
textField.textProperty().addListener((observable, oldText, newText)->{ // lambda style
textField1.setText(newText); // update me when any change happens
// so you can grab the changes from here.
});
}
public static void main(String[] args) {
launch();
}
}
Test

Add String row to TableView in JAVA FX

I can't find a way to add a simple "String" row to my tableView.
In fact i can add a row but its content is not visible ...
Here is my code:
#FXML
private TableView<String> table;
#FXML
private TableColumn<String, String> table2;
public ObservableList<String> getLanes()
{
ObservableList<String> lanes=FXCollections.observableArrayList();
lanes.add("TEST");
return lanes;
}
Then:
table.setItems(getLanes()); //Not working
and
table.getItems().add("TEST"); //Not working
But without success.
I read that and that as well as other documentations but it did not help me to do it in this simple way.
EDIT:
Adding this line solved my problem:
table2.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue()));
Here is a simple application where we are trying to load a single value into a TableView column. It also shows how to set a cellValueFactory() on a table column.
tableColumn.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue()));
MCVE
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
TableView<String> tableView = new TableView<>();
TableColumn<String, String> tableColumn = new TableColumn<>("Name");
tableColumn.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue()));
tableView.getColumns().add(tableColumn);
ObservableList<String> items = FXCollections.observableArrayList("Itachi");
tableView.setItems(items);
VBox root = new VBox(tableView);
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 300, 275);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Categories