Note: the description is changed (from that in the original report) because its expectation ("Action events should only be triggered when a user interacts with the combobox and changes the value themselves.") was wrong (see doc citation in Kevin's comment below).
Nevertheless, the behavior of firing an action after setAll (as demonstrated in the example) is wrong in two aspects:
A) run as-is (that is with an initial selected value that's contained in both lists, though at a different index in each - "blue")
- press the button: note that the selected value is still the inital (blue)
- expected: no trigger of action
- actual: action triggered twice, first with null, then with blue
B) change initial value to "black" (== contained in original list, uncontained in new)
- press the button: note that the selected value is pink (the item at the same index as the initial value in the old list)
- expected: action triggered
- actual: no action triggered
ADDITIONAL SYSTEM INFORMATION :
Windows 10, Openjfx 11.0.2 via maven
A DESCRIPTION OF THE PROBLEM :
See this stack overflow question I posted:
https://stackoverflow.com/questions/66674211/combobox-fires-action-event-when-underlying-data-is-modified?noredirect=1#comment117901023_66674211
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create the example provided in the stack overflow question.
Run the example, choose a new colour in the dropdown, click the button. Repeat.
Note the console log.
The code can be modified to instead attach a listener to the valueproperty, results will be the same.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
see above
---------- BEGIN SOURCE ----------
package sample;
import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
public class Main extends Application {
ObservableList<String> theList = FXCollections.observableArrayList();
@Override
public void start(Stage primaryStage) throws Exception{
primaryStage.setTitle("Sample");
FlowPane root = new FlowPane(Orientation.VERTICAL);
root.setVgap(20);
List<String> initialColors = Arrays.asList("red", "green", "blue", "black");
theList.addAll(initialColors);
ComboBox<String> theComboBox = new ComboBox<>();
theComboBox.setItems(theList);
// theComboBox.setOnAction( event -> {
// System.out.println(String.format("theComboBox action listener triggered, current value is %s", theComboBox.getValue()));
// });
theComboBox.valueProperty().addListener((observable, oldValue, newValue)->{
System.out.println(String.format("theComboBox action listener triggered, current value is %s", theComboBox.getValue()));
});
Button bttn1 = new Button("Press me");
bttn1.setOnAction(event -> {
List<String> someColors = Arrays.asList("red", "orange", "mauve", "pink", "blue", "salmon", "chiffon");
System.out.println("About to issue setAll against observable list");
theList.setAll(someColors);
});
root.getChildren().add(theComboBox);
root.getChildren().add(bttn1);
primaryStage.setScene(new Scene(root, 100, 150));
primaryStage.show();
System.out.println("Setting initial selection to \"blue\"");
theComboBox.setValue("blue");
}
public static void main(String[] args) {
launch(args);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
(was: use a flag variable in the listener - for the original report, that is not wanting to be notified when value changes are triggered by modifying the items via setAll)
FREQUENCY : always
Nevertheless, the behavior of firing an action after setAll (as demonstrated in the example) is wrong in two aspects:
A) run as-is (that is with an initial selected value that's contained in both lists, though at a different index in each - "blue")
- press the button: note that the selected value is still the inital (blue)
- expected: no trigger of action
- actual: action triggered twice, first with null, then with blue
B) change initial value to "black" (== contained in original list, uncontained in new)
- press the button: note that the selected value is pink (the item at the same index as the initial value in the old list)
- expected: action triggered
- actual: no action triggered
ADDITIONAL SYSTEM INFORMATION :
Windows 10, Openjfx 11.0.2 via maven
A DESCRIPTION OF THE PROBLEM :
See this stack overflow question I posted:
https://stackoverflow.com/questions/66674211/combobox-fires-action-event-when-underlying-data-is-modified?noredirect=1#comment117901023_66674211
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create the example provided in the stack overflow question.
Run the example, choose a new colour in the dropdown, click the button. Repeat.
Note the console log.
The code can be modified to instead attach a listener to the valueproperty, results will be the same.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
see above
---------- BEGIN SOURCE ----------
package sample;
import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
public class Main extends Application {
ObservableList<String> theList = FXCollections.observableArrayList();
@Override
public void start(Stage primaryStage) throws Exception{
primaryStage.setTitle("Sample");
FlowPane root = new FlowPane(Orientation.VERTICAL);
root.setVgap(20);
List<String> initialColors = Arrays.asList("red", "green", "blue", "black");
theList.addAll(initialColors);
ComboBox<String> theComboBox = new ComboBox<>();
theComboBox.setItems(theList);
// theComboBox.setOnAction( event -> {
// System.out.println(String.format("theComboBox action listener triggered, current value is %s", theComboBox.getValue()));
// });
theComboBox.valueProperty().addListener((observable, oldValue, newValue)->{
System.out.println(String.format("theComboBox action listener triggered, current value is %s", theComboBox.getValue()));
});
Button bttn1 = new Button("Press me");
bttn1.setOnAction(event -> {
List<String> someColors = Arrays.asList("red", "orange", "mauve", "pink", "blue", "salmon", "chiffon");
System.out.println("About to issue setAll against observable list");
theList.setAll(someColors);
});
root.getChildren().add(theComboBox);
root.getChildren().add(bttn1);
primaryStage.setScene(new Scene(root, 100, 150));
primaryStage.show();
System.out.println("Setting initial selection to \"blue\"");
theComboBox.setValue("blue");
}
public static void main(String[] args) {
launch(args);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
(was: use a flag variable in the listener - for the original report, that is not wanting to be notified when value changes are triggered by modifying the items via setAll)
FREQUENCY : always
- relates to
-
JDK-8279138 ComboBox with content binding loses selected value when list updated with setAll
- Open
-
JDK-8279140 ComboBox can lose selected value on item change via setAll
- Resolved
-
JDK-8279139 ComboBox loses selected value on second interactive item change via setAll
- Closed