-
Bug
-
Resolution: Unresolved
-
P3
-
jfx11
Happens with an not-editable comboBox when setting a value that's not contained in the items "later" (than on startup) in its lifetime.
To reproduce, compile and run the example below
- click the button to set an uncontained value
- expected and actual: uncontained value shown
- open the dropdown and select a contained value
- expected and actual: selected item shown
- again click the button
- expected: uncontained value shown
- actual: buttonCell showing nothing
The misbehavior turned up on SO https://stackoverflow.com/q/55378762/203657 and feels like a regression: the (very) oldJDK-8127575 which exhibited the not-showing always, it was fixed some years ago.
It might have been re-introduced by fixingJDK-8145588 (make sure that cell's selected property is updated in updateItem to allow for custom styles for that state) - at least removing that fix resulted in correct showing.
The flow of control for updating a uncontained value in the skins is:
1. listener to valueProperty calls - implicitely - comboBoxListViewSkin.updateDisplayNode
2. if uncontained it reaches the snippet:
//RT-21336 Show the ComboBox value even though it doesn't
// exist in the ComboBox items list (part two of fix)
buttonCell.updateIndex(-1);
boolean empty = updateDisplayText(buttonCell, value, false);
3. the updateIndex(-1) leads to marking the cell as dirty (bug fixJDK-8145588, done in cell.updateSelected)
if (wasSelected != selected) {
markCellDirty();
}
// itemDirty and markCellDirty introduced as a solution forJDK-8145588.
// In the fullness of time, a more fully developed solution can be developed
// that offers a public API around this lazy-dirty impl.
private boolean itemDirty = false;
private final void markCellDirty() {
itemDirty = true;
requestLayout();
}
4. updateDisplayText changes the cell's text/empty properties under its feet, that is after doing this, cell.item != cell.text:
cell.setText(s);
cell.setGraphic(null);
5. (last act ;) at layout time of the cell, the dirty marker triggers an updateItem with the cell's item (which at this time is != cell.text, see 4)
if (itemDirty) {
updateItem(getItem(), isEmpty());
itemDirty = false;
}
On the whole there are two fishy parts:
- changing cell properties under its feet
- the dirty hot fix to guarantee valid selected in updateItem
Not entirely certain how this can be fixed: the former might require a cell that can handle uncontained values on its own, the latter has deeper roots, see the discussion in the bug report
Finally, the example to reproduce:
public class ComboUncontainedBug extends Application {
private Parent createContent() {
ComboBox<String> combo = new ComboBox<>(
FXCollections.observableArrayList("Option 1", "Option 2", "Option 3")) ;
Button uncontained = new Button("set value to uncontained");
uncontained.setOnAction(e -> combo.setValue("uncontained value"));
VBox content = new VBox(10, combo, uncontained);
return content;
}
@Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(createContent()));
//stage.setTitle(FXUtils.version());
stage.show();
}
public static void main(String[] args) {
launch(args);
}
@SuppressWarnings("unused")
private static final Logger LOG = Logger
.getLogger(ComboUncontainedBug.class.getName());
}
To reproduce, compile and run the example below
- click the button to set an uncontained value
- expected and actual: uncontained value shown
- open the dropdown and select a contained value
- expected and actual: selected item shown
- again click the button
- expected: uncontained value shown
- actual: buttonCell showing nothing
The misbehavior turned up on SO https://stackoverflow.com/q/55378762/203657 and feels like a regression: the (very) old
It might have been re-introduced by fixing
The flow of control for updating a uncontained value in the skins is:
1. listener to valueProperty calls - implicitely - comboBoxListViewSkin.updateDisplayNode
2. if uncontained it reaches the snippet:
//
// exist in the ComboBox items list (part two of fix)
buttonCell.updateIndex(-1);
boolean empty = updateDisplayText(buttonCell, value, false);
3. the updateIndex(-1) leads to marking the cell as dirty (bug fix
if (wasSelected != selected) {
markCellDirty();
}
// itemDirty and markCellDirty introduced as a solution for
// In the fullness of time, a more fully developed solution can be developed
// that offers a public API around this lazy-dirty impl.
private boolean itemDirty = false;
private final void markCellDirty() {
itemDirty = true;
requestLayout();
}
4. updateDisplayText changes the cell's text/empty properties under its feet, that is after doing this, cell.item != cell.text:
cell.setText(s);
cell.setGraphic(null);
5. (last act ;) at layout time of the cell, the dirty marker triggers an updateItem with the cell's item (which at this time is != cell.text, see 4)
if (itemDirty) {
updateItem(getItem(), isEmpty());
itemDirty = false;
}
On the whole there are two fishy parts:
- changing cell properties under its feet
- the dirty hot fix to guarantee valid selected in updateItem
Not entirely certain how this can be fixed: the former might require a cell that can handle uncontained values on its own, the latter has deeper roots, see the discussion in the bug report
Finally, the example to reproduce:
public class ComboUncontainedBug extends Application {
private Parent createContent() {
ComboBox<String> combo = new ComboBox<>(
FXCollections.observableArrayList("Option 1", "Option 2", "Option 3")) ;
Button uncontained = new Button("set value to uncontained");
uncontained.setOnAction(e -> combo.setValue("uncontained value"));
VBox content = new VBox(10, combo, uncontained);
return content;
}
@Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(createContent()));
//stage.setTitle(FXUtils.version());
stage.show();
}
public static void main(String[] args) {
launch(args);
}
@SuppressWarnings("unused")
private static final Logger LOG = Logger
.getLogger(ComboUncontainedBug.class.getName());
}
- duplicates
-
JDK-8259562 ComboBox no longer renders item which isn't in the list
-
- Closed
-
- relates to
-
JDK-8145588 Custom rendering for selected ComboBox list item fails
-
- Resolved
-
-
JDK-8127575 Not editable ComboBox does not paint value setting by code (setValue()) when it does not exist in the list.
-
- Closed
-