-
Bug
-
Resolution: Unresolved
-
P4
-
jfx11.0.12
-
x86_64
-
windows_10
ADDITIONAL SYSTEM INFORMATION :
Observed on Windows 10
Failing configuration:
Java: Temurin JDK 11.0.12+7
JavaFX: javafx-sdk-11.0.2
Successful configuration:
Java/JavaFX: liberica JDK 8u302-full
A DESCRIPTION OF THE PROBLEM :
In Java 11 with JavaFX SDK 11, a call to ListView.getSelectedItem() will return the previously selected item if called from the invalidation listener on ListView.getSelectionModel().getSelectedItems().
It works just fine on Liberica's Java 8 build that includes JavaFX bundled inside.
REGRESSION : Last worked in version 8u301
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the included code and watch as the list items get selected once per second. Note that the label will not match the selected item.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Label should always match the selected item in the list.
ACTUAL -
Label will match the selected item in the list if the user selects an item in a list. However if the list item is selected programmatically (which will happen once per second in this example code) the label will show the value of the previously selected item.
---------- BEGIN SOURCE ----------
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class ListViewBugDemo extends Application{
@Override
public void start(Stage primaryStage) throws Exception {
Pane root = new FlowPane();
ListView<String> list = new ListView<>();
list.getItems().addAll("One", "Two", "Three");
Label selectedItemLabel = new Label();
//This way works just fine
// selectedItemLabel.textProperty().bind(list.getSelectionModel().selectedItemProperty());
//This way also works just fine
// selectedItemLabel.textProperty().bind(
// Bindings.createStringBinding(
// () -> list.getSelectionModel().getSelectedItems().isEmpty() ? null : list.getSelectionModel().getSelectedItems().get(0),
// list.getSelectionModel().getSelectedItems())
// );
//This way results in a binding that always has the previously selected item
selectedItemLabel.textProperty().bind(
Bindings.createStringBinding(
() -> list.getSelectionModel().getSelectedItem(),
list.getSelectionModel().getSelectedItems())
);
root.getChildren().addAll(list, selectedItemLabel);
primaryStage.setScene(new Scene(root, 400, 400));
primaryStage.show();
new Thread(() -> {
while(true) {
try {
Thread.sleep(1000);
Platform.runLater(() -> list.getSelectionModel().select((list.getSelectionModel().getSelectedIndex() + 1) % list.getItems().size()));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}).start();
}
public static void main(String[] args) {
launch(args);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Replace the binding with either of the commented out bindings above it.
FREQUENCY : always
Observed on Windows 10
Failing configuration:
Java: Temurin JDK 11.0.12+7
JavaFX: javafx-sdk-11.0.2
Successful configuration:
Java/JavaFX: liberica JDK 8u302-full
A DESCRIPTION OF THE PROBLEM :
In Java 11 with JavaFX SDK 11, a call to ListView.getSelectedItem() will return the previously selected item if called from the invalidation listener on ListView.getSelectionModel().getSelectedItems().
It works just fine on Liberica's Java 8 build that includes JavaFX bundled inside.
REGRESSION : Last worked in version 8u301
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the included code and watch as the list items get selected once per second. Note that the label will not match the selected item.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Label should always match the selected item in the list.
ACTUAL -
Label will match the selected item in the list if the user selects an item in a list. However if the list item is selected programmatically (which will happen once per second in this example code) the label will show the value of the previously selected item.
---------- BEGIN SOURCE ----------
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class ListViewBugDemo extends Application{
@Override
public void start(Stage primaryStage) throws Exception {
Pane root = new FlowPane();
ListView<String> list = new ListView<>();
list.getItems().addAll("One", "Two", "Three");
Label selectedItemLabel = new Label();
//This way works just fine
// selectedItemLabel.textProperty().bind(list.getSelectionModel().selectedItemProperty());
//This way also works just fine
// selectedItemLabel.textProperty().bind(
// Bindings.createStringBinding(
// () -> list.getSelectionModel().getSelectedItems().isEmpty() ? null : list.getSelectionModel().getSelectedItems().get(0),
// list.getSelectionModel().getSelectedItems())
// );
//This way results in a binding that always has the previously selected item
selectedItemLabel.textProperty().bind(
Bindings.createStringBinding(
() -> list.getSelectionModel().getSelectedItem(),
list.getSelectionModel().getSelectedItems())
);
root.getChildren().addAll(list, selectedItemLabel);
primaryStage.setScene(new Scene(root, 400, 400));
primaryStage.show();
new Thread(() -> {
while(true) {
try {
Thread.sleep(1000);
Platform.runLater(() -> list.getSelectionModel().select((list.getSelectionModel().getSelectedIndex() + 1) % list.getItems().size()));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}).start();
}
public static void main(String[] args) {
launch(args);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Replace the binding with either of the commented out bindings above it.
FREQUENCY : always