Javafx Cascading dropdown based on selection - combobox

am migrating from swing to javafx. Can anyone help with a link/code snippet on how to cascade combobox(es) based on parent-child selection in javafxe.g. country-state, branch-department-unit.

Use this code:for basic drop down example
package comboboxexamplestackoverflow;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
/**
*
* #author reegan
*/
public class ComboBoxExampleStackOverFlow extends Application {
#Override
public void start(Stage primaryStage) {
HBox box = new HBox(20);
box.setPadding(new Insets(10, 10, 10, 10));
ObservableList<String> countries =
FXCollections.observableArrayList(
"India",
"Germany",
"Israel");
final ObservableList<String> indiaStates =
FXCollections.observableArrayList(
"StatesIndia1",
"StatesIndia2",
"StatesIndia3");
final ObservableList<String> germanyStates =
FXCollections.observableArrayList(
"StatesGermany1",
"StatesGermany2",
"StatesGermany3");
final ObservableList<String> israelStates =
FXCollections.observableArrayList(
"StatesIsrael1",
"StatesIsrael2",
"StatesIsrael3");
ComboBox comboBox1 = new ComboBox(countries);
final ComboBox comboBox2 = new ComboBox();
comboBox1.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
#Override
public void changed(ObservableValue ov, Object t, Object t1) {
switch (t1.toString()) {
case "India":
comboBox2.setItems(indiaStates);
break;
case "Germany":
comboBox2.setItems(germanyStates);
break;
case "Israel":
comboBox2.setItems(israelStates);
break;
}
}
});
box.getChildren().addAll(comboBox1, comboBox2);
Scene scene = new Scene(box, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* The main() method is ignored in correctly deployed JavaFX application.
* main() serves only as fallback in case the application can not be
* launched through deployment artifacts, e.g., in IDEs with limited FX
* support. NetBeans ignores main().
*
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}

Do it basically the same way as you would in Swing.
Use combo.getSelectionModel().selectedItemProperty().addListener() to add a ChangeListener that will be called whenever the combo box's selection changes.
See here for basic introduction to Combo Box : http://docs.oracle.com/javafx/2/ui_controls/combo-box.htm#BABJCCIB

Related

JAVAFX Text Animation From Array

This is very much a work in progress so I apologize for my code needing to be cleaned up, but I thought it best to include everything I have so far.
I'm trying to figure how to animate text by looping through an array of images. My code loops through the array and displays just the last image. I need to display one image at a time and repeat to give the desired animation effect. What am I doing wrong or not doing?
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.stage.Stage;
import javafx.util.Duration;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.event.EventHandler;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
public class ImageAnimatorWithAudio extends Application {
private final static int NUMBER_OF_SLIDES = 10;
#Override // Override the start method in the Application class
public void start(Stage primaryStage) {
Image[] images = new Image[NUMBER_OF_SLIDES];
Timeline animation = new Timeline(new KeyFrame(Duration.millis(5000)));
animation.setCycleCount(Timeline.INDEFINITE);
animation.play();
HBox hBox = new HBox();
hBox.setSpacing(10);
hBox.setAlignment(Pos.TOP_RIGHT);
Button btStartPause = new Button("Start Animation");
hBox.getChildren().add(btStartPause);
//Create border pane
BorderPane borderPane = new BorderPane();
borderPane.setTop(hBox); //Add hBox to borderPane
BorderPane.setAlignment(hBox, Pos.TOP_RIGHT); //Align hBox
btStartPause.setOnAction(e -> {
if (btStartPause.getText().equals("Start Animation")) {
btStartPause.setText("Pause Animation");
animation.play();
} else {
btStartPause.setText("Start Animation");
animation.pause();
}
});
GridPane pane = new GridPane();
pane.setPadding(new Insets(5,5,5,5));
for (int i = 0; i < NUMBER_OF_SLIDES; i++) {
images[i] = new Image("image_path" + i + ".png"); //file names are numerically named(i)
pane.getChildren().add(new ImageView(images[i]));
}
pane.getChildren().add(borderPane);
Scene scene = new Scene(pane, 450, 450);
primaryStage.setTitle("TextAnimation"); //Set the stage title
primaryStage.setScene(scene); //Place the scene in the stage
primaryStage.show(); //Display the stage
}
public static void main(String[] args){
Application.launch(args);
}
}
Any help is appreciated.
Here is an app that demonstrates how to add Images to an ArrayList(similar approach for an Array). It also demonstrates how to load those Images into an ImageView and change them using Timeline.
Main
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* #author Sedrick
*/
public class JavaFXApplication1 extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" prefHeight="371.0" prefWidth="607.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.60" fx:controller="javafxapplication1.FXMLDocumentController">
<children>
<Button fx:id="btnMain" layoutX="263.0" layoutY="326.0" onAction="#handleButtonAction" text="Click Me!" />
<Label fx:id="lblMain" layoutX="269.0" layoutY="28.0" minHeight="16" minWidth="69" />
<ImageView fx:id="ivMain" fitHeight="201.0" fitWidth="278.0" layoutX="165.0" layoutY="85.0" pickOnBounds="true" preserveRatio="true" />
</children>
</AnchorPane>
Controller
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.util.Duration;
/**
*
* #author Sedrick
*/
public class FXMLDocumentController implements Initializable {
#FXML private Label lblMain;
#FXML private ImageView ivMain;
#FXML private Button btnMain;
Timeline timeline;
List<Image> imageContainer;
int currentImageBeingDisplayed;
#FXML
private void handleButtonAction(ActionEvent event) {
lblMain.setText("Animation started!");
currentImageBeingDisplayed = 0;
timeline.play();
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
//Load images
imageContainer = new ArrayList();
for(int i = 1; i <= 12; i++)
{
try
{
System.out.println("/images/Slide" + i + ".PNG");
imageContainer.add(new Image(getClass().getResource("/images/Slide" + i + ".PNG").toURI().toString()));
} catch (URISyntaxException ex) {
System.out.println(ex.toString());
}
}
//Change the image every second
timeline = new Timeline(
new KeyFrame(
Duration.seconds(1),
new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent actionEvent) {
Platform.runLater(()->{
ivMain.setImage(imageContainer.get(currentImageBeingDisplayed++));
});
}
}
)
);
timeline.setCycleCount(12);
}
}
Output:(looks similar to below)

How to save entire object for a checkbox in javafx

I have number of objects. Let's say i have 10 Books object and i want user to select any number of the book. When user press the submit button i want to retrieve all the books "object" that user selected.
As of now, while showing screen to user i use
CheckBox cb= new CheckBox(book.getName());
this shows bookname to user and user selects the book. But on runtime i will be needing bookid and other properties of book object as well.
Is there anyway through which i can save the book object in the checkbox?
Basic Examle. if you want more sepecifc you need to post your code, we can set object to node using setUserDate, then we can use that object when we need. here i am using object id for example, in yor case save that object i hope this will solve your problem ,?s post a comment
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class UserData extends Application {
public void start(Stage primaryStage) {
VBox root = new VBox();
Book book = new Book(22, "firstBok");
Book book1 = new Book(2, "secondBok");
CheckBox checkB = new CheckBox(book.getName());
checkB.setUserData(book);
CheckBox checkB1 = new CheckBox(book1.getName());
checkB1.setUserData(book1);
Button btn = new Button("Submit");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
if (checkB.isSelected()) {
int firstCheckBxId = ((Book) checkB.getUserData()).getId();
System.out.println("id:" + firstCheckBxId);
}
if (checkB1.isSelected()) {
int secondCheckBxId = ((Book) checkB1.getUserData()).getId();
System.out.println("id:" + secondCheckBxId);
}
}
});
root.getChildren().addAll(checkB, checkB1, btn);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
class Book {
int id;
private String name;
Book(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return this.id;
}
public String getName() {
return name;
}
}
public static void main(String[] args) {
launch(args);
}
}
Consider using a control with built-in selection functionality, such as a ListView. Then you can just check the selection model.
import java.util.stream.IntStream;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class BookSelection extends Application {
#Override
public void start(Stage primaryStage) {
ListView<Book> bookList = new ListView<>();
bookList.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
bookList.setCellFactory(lv -> new ListCell<Book>() {
#Override
public void updateItem(Book book, boolean empty) {
super.updateItem(book, empty);
if (empty) {
setText(null);
} else {
setText(book.getTitle());
}
}
});
IntStream.rangeClosed(1, 10).mapToObj(i -> new Book("Book "+i)).forEach(bookList.getItems()::add);
Button submit = new Button("Submit selection");
submit.setOnAction(e ->
bookList.getSelectionModel().getSelectedItems().forEach(book -> System.out.println(book.getTitle())));
BorderPane root = new BorderPane(bookList, null, null, submit, null);
BorderPane.setAlignment(submit, Pos.CENTER);
BorderPane.setMargin(submit, new Insets(10));
Scene scene = new Scene(root, 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
public static class Book {
private final StringProperty title = new SimpleStringProperty() ;
public Book(String title) {
setTitle(title);
}
public final StringProperty titleProperty() {
return this.title;
}
public final java.lang.String getTitle() {
return this.titleProperty().get();
}
public final void setTitle(final java.lang.String title) {
this.titleProperty().set(title);
}
}
public static void main(String[] args) {
launch(args);
}
}
If for some reason you really want to implement this with check boxes, you can keep a Set<Book> representing the selected books, and update it when each check box is selected/unselected. Note this is similar to #user99370's answer, but is more robust as it avoids downcasting the (essentially unknown-type) userData to your data type.
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
public class BookSelection extends Application {
#Override
public void start(Stage primaryStage) {
GridPane grid = new GridPane();
grid.setHgap(5);
grid.setVgap(5);
grid.setPadding(new Insets(10 ));
List<Book> books = IntStream.rangeClosed(1, 10).mapToObj(i -> new Book("Book "+i)).collect(Collectors.toList());
Set<Book> selectedBooks = new HashSet<>();
int row = 0 ;
for (Book book : books) {
CheckBox checkBox = new CheckBox();
checkBox.selectedProperty().addListener((obs, wasSelected, isNowSelected) -> {
if (isNowSelected) {
selectedBooks.add(book);
} else {
selectedBooks.remove(book);
}
});
grid.addRow(row, checkBox, new Label(book.getTitle()));
row++ ;
}
Button submit = new Button("Submit selection");
submit.setOnAction(e ->
selectedBooks.forEach(book -> System.out.println(book.getTitle())));
GridPane.setHalignment(submit, HPos.CENTER);
grid.add(submit, 0, row, 2, 1);
Scene scene = new Scene(grid, 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
public static class Book {
private final StringProperty title = new SimpleStringProperty() ;
public Book(String title) {
setTitle(title);
}
public final StringProperty titleProperty() {
return this.title;
}
public final java.lang.String getTitle() {
return this.titleProperty().get();
}
public final void setTitle(final java.lang.String title) {
this.titleProperty().set(title);
}
}
public static void main(String[] args) {
launch(args);
}
}
This is just a simplified version of the accepted answer.
We can use setUserData(Object) to set data and getUserData() to retrieve the previously set data of any JavaFX node (including CheckBox).
Reference:
https://docs.oracle.com/javase/8/javafx/api/javafx/scene/Node.html#setUserData-java.lang.Object-

How to temporarily remove items from a ChoiceBox (or maybe a ComboBox)?

I've come across a somewhat perplexing conundrum. I've recently started to figure out how to work with listeners, thanks to some people on here, and I'm trying to find a way to use them in conjunction with choice/comboboxes to do something tricky. What I want to have happen is, when the user makes a selection from one of six linked boxes containing six choices, it removes that option from the other 5 boxes until either A: the option is changed to one of the remaining ones, or B: the option is changed to a null or default setting (to prevent getting "locked in" after picking, or maybe I can just make a reset button for that purpose). I've got a ChangeListener on each choicebox now, but various things I've tried (switch statements, assigning each answer a boolean, various attempts to use .getItems().remove() in vain, I've been at this a while) Has anyone figured or seen an example of how this could be done? Thanks in advance for any advice, you guys(and gals) have helped me learn by leaps and bounds these past few weeks.
if you want something like this:
I had this code in my program. it is nor really efficient, but was fine for me on a small set of data.
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.ChoiceBox;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class ConnectedComboBox<T> implements ChangeListener<T> {
private ObservableList<T> items;
private List<ChoiceBox<T>> comboBoxList = new ArrayList<>();
public ConnectedComboBox(ObservableList<T> items){
this.items = items;
if (this.items == null) this.items = FXCollections.observableArrayList();
}
public void addComboBox(ChoiceBox<T> comboBox){
comboBoxList.add(comboBox);
comboBox.valueProperty().addListener(this);
updateSelection();
}
public void removeComboBox(ChoiceBox<T> comboBox){
comboBoxList.remove(comboBox);
comboBox.valueProperty().removeListener(this);
updateSelection();
}
// this boolean needed because we can set combobox Value in updateSelection()
// this will trigger a value listener and update selection one more time => stack overflow
// this behavior occurs only if we have more than one equal item in source ObservableList<T> items list.
private boolean updating = false;
private void updateSelection() {
if (updating) return;
updating = true;
List<T> availableChoices = items.stream().collect(Collectors.toList());
for (ChoiceBox<T> comboBox: comboBoxList){
if (comboBox.getValue()!= null) {
availableChoices.remove(comboBox.getValue());
}
}
for (ChoiceBox<T> comboBox: comboBoxList){
T selectedValue = comboBox.getValue();
ObservableList<T> items = comboBox.getItems();
items.setAll(availableChoices);
if (selectedValue != null) {
items.add(selectedValue);
comboBox.setValue(selectedValue);
}
}
updating = false;
}
#Override
public void changed(ObservableValue<? extends T> observable, T oldValue, T newValue) {
updateSelection();
}
}
And here is how you use it:
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ChoiceBox;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class MainFX extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
HBox root = new HBox();
root.setSpacing(10);
ObservableList<String> values = FXCollections.observableArrayList("One", "Two", "Three", "Four","Five");
ChoiceBox<String> combo1 = new ChoiceBox<>();
combo1.setPrefWidth(100);
ChoiceBox<String> combo2 = new ChoiceBox<>();
combo2.setPrefWidth(100);
ChoiceBox<String> combo3 = new ChoiceBox<>();
combo3.setPrefWidth(100);
root.getChildren().addAll(combo1,combo2,combo3);
ConnectedComboBox<String> connectedComboBox = new ConnectedComboBox<>(values);
connectedComboBox.addComboBox(combo1);
connectedComboBox.addComboBox(combo2);
connectedComboBox.addComboBox(combo3);
primaryStage.setScene(new Scene(root,600,600));
primaryStage.show();
}
public static void main(String[] args){
launch(args);
}
}

Combobox refresh value and listview when object content change

I would like to update my combobox when the content of the object used to display text in combo changes.
Here is a sample:
package com.javafx.example.combobox;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;
import javafx.util.StringConverter;
public class ComboboxSample extends Application {
class Sequence {
public StringProperty name = new SimpleStringProperty();
public Sequence(String name) {
super();
this.name.set(name);
}
#Override
public String toString() {
return "null";
}
}
#Override
public void start(Stage stage) throws Exception {
stage.setTitle("ComboBoxSample");
ComboBox<Sequence> combo = new ComboBox<>();
combo.setItems(FXCollections.observableArrayList(
new Sequence("Toto"),
new Sequence("Titi")));
combo.getSelectionModel().selectFirst();
combo.setConverter(new StringConverter<ComboboxSample.Sequence>() {
#Override
public String toString(Sequence sequence) {
return sequence.name.get();
}
#Override
public Sequence fromString(String string) {
System.out.println("call fromString");
return null;
}
});
TextField text = new TextField();
Button renameButton = new Button("Rename");
renameButton.setOnAction(evt -> combo.getValue().name.set(text.getText()));
HBox root = new HBox(combo, text, renameButton);
HBox.setHgrow(text, Priority.ALWAYS);
stage.setScene(new Scene(root));
stage.show();
}
public static void main(String... args) {
launch(args);
}
}
The combobox contains objects with a property name. If i rename this property, the display do not change or sometimes it changes but not all the time. It is the standard behavior as the combobox update when the object changes, and not when its content changes.
How can i do to force the combobox to refresh its value and the listview on change?
Thanks
EDIT1:
Using a callback in an observaleList seems to be a solution.
package com.javafx.example.combobox;
import javafx.application.Application;
import javafx.beans.Observable;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.StringConverter;
public class ComboboxSample extends Application {
ObservableList<Sequence> sequences;
class Sequence {
public StringProperty name = new SimpleStringProperty();
public Sequence(String name) {
super();
this.name.set(name);
}
#Override
public String toString() {
return "null";
}
}
#Override
public void start(Stage stage) throws Exception {
stage.setTitle("ComboBoxSample");
Callback<Sequence, Observable[]> extractor = new Callback<Sequence, Observable[]>() {
#Override
public Observable[] call(Sequence s) {
return new Observable[] {s.name};
}
};
sequences = FXCollections.observableArrayList(extractor);
sequences.addAll(
new Sequence("Toto"),
new Sequence("Titi"));
ComboBox<Sequence> combo = new ComboBox<>();
combo.setItems(sequences);
combo.getSelectionModel().selectFirst();
combo.setConverter(new StringConverter<ComboboxSample.Sequence>() {
#Override
public String toString(Sequence sequence) {
return sequence.name.get();
}
#Override
public Sequence fromString(String string) {
System.out.println("call fromString");
return null;
}
});
combo.valueProperty().addListener((obs, oldValue, newValue) -> System.out.println("Change from " + oldValue.name.get() + " to " + newValue.name.get()));
TextField text = new TextField();
Button renameButton = new Button("Rename");
renameButton.setOnAction(evt -> {
combo.getValue().name.set(text.getText());
});
HBox root = new HBox(combo, text, renameButton);
HBox.setHgrow(text, Priority.ALWAYS);
stage.setScene(new Scene(root));
stage.show();
}
public static void main(String... args) {
launch(args);
}
}
Everytime a new value is added to the object list, set the combobox value again. Works for me. I did a small example to show this. Hope it is helpful
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ComboTest extends Application {
int i =0;
ObservableList<String> list = FXCollections.observableArrayList("A","B");
ComboBox<String> combo = new ComboBox();
#Override
public void start(Stage primaryStage) {
Button btn = new Button();
combo.setPromptText("Testing combobox");
combo.setPrefWidth(300);
btn.setText("Add items to list");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
list.add(String.valueOf(i));
System.out.println("size of list " + list.size() );
i++;
combo.setItems(list);
}
});
combo.setItems(list);
VBox root = new VBox();
root.getChildren().addAll(btn,combo);
root.setSpacing(20);
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}

How selected items from one combobox change specific items on second Combobox?

Combobox1 has 3 items (Spain, France, UK) and Combobox2 6 items (Barcelona, Madrid, Paris, Marseille, London, Bristol).
When one item is selected from Combobox1 (Spain) it should be available to Combobox2 the specific items (Barcelona, Madrid).
Can anyone help me with this?
Thanks in advance
Three combox listener example code.i think this solution use ful for your.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package threecombobox;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
/**
*
* #author reegan
*/
public class ThreeComboBox extends Application {
#Override
public void start(Stage primaryStage) {
List combox1List = new ArrayList();
for (int i = 1; i < 10; i++) {
combox1List.add(i);
}
final Map combox2Map = new HashMap();
for (int i = 0; i < combox1List.size(); i++) {
List l = new ArrayList();
for (int j = 1; j < 10; j++) {
int k = (int) combox1List.get(i) * 10 + j;
l.add(k);
}
combox2Map.put(combox1List.get(i), l);
}
final Map combox3Map = new HashMap();
for (Object o : combox1List) {
for (Object o1 : (List) combox2Map.get(o)) {
List l = new ArrayList();
for (int i = 1; i < 10; i++) {
int value = (int) o1 * 10 + i;
l.add(value);
}
combox3Map.put(o1, l);
}
}
ObservableList combox1 = FXCollections.observableList(combox1List);
HBox box = new HBox(20);
box.setPadding(new Insets(20, 20, 20, 20));
ComboBox cb1 = new ComboBox();
final ComboBox cb2 = new ComboBox();
final ComboBox cb3 = new ComboBox();
cb1.setItems(combox1);
cb1.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
#Override
public void changed(ObservableValue ov, Object t, Object t1) {
ObservableList combox2 = FXCollections.observableArrayList((List) combox2Map.get(t1));
cb2.setItems(combox2);
}
});
cb2.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
#Override
public void changed(ObservableValue ov, Object t, Object t1) {
if (t1 != null) {
ObservableList combox3 = FXCollections.observableArrayList((List) combox3Map.get(t1));
cb3.setItems(combox3);
}
}
});
box.getChildren().addAll(cb1, cb2, cb3);
Scene scene = new Scene(box, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* The main() method is ignored in correctly deployed JavaFX application.
* main() serves only as fallback in case the application can not be
* launched through deployment artifacts, e.g., in IDEs with limited FX
* support. NetBeans ignores main().
*
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Well, we don't know your data structure, but if a city is attached to a country, add a listener to your country combobox and each time the selection change, you reconfigure the items on the city combobox.
I'll do something like that :
ComboBox<City> cityBox;
ComboBox<Country> countryBox;
countryBox.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
#Override
public void changed(ObservableValue observableValue, Country oldCountry, Country newCountry) {
//Here configure your cityBox corresponding with newCountry
}
});
or with binding
cityBox.itemsProperty().bind(new ListBinding<City>() {
{
bind(cityBox.getSelectionModel().selectedItemProperty());
}
#Override
protected ObservableList<City> computeValue() {
Country country = countryBox.getValue();
// add the city corresponding to the country on a new list
return //The list with the city filtered with the country
}
});

Resources