Issue
I have combobox with custom ListCell:
private class SeverityCell extends ListCell<CustomItem> {
private final CustomBox custombox;
{
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
custombox = new CustomBox();
}
@Override
protected void updateItem(CustomItem item, boolean empty) {
super.updateItem(item, empty);
if (null != item) {
//...
}
setGraphic(custombox);
}
}
and
combobox.setCellFactory(new Callback<ListView<CustomItem>, ListCell<CustomItem>>() {
@Override public ListCell<CustomItem> call(ListView<CustomItem> p) {
return new SeverityCell();
}
});
When I click on mu custom component popup closes, but I want to avoid it. Which method/event I need to override?
Solution
ComboBox
internally utilizes ListView
for rendering its items. Also its skin class is ComboBoxListViewSkin
. In a source code of this class there is boolean flag to control popup hiding behavior:
// Added to allow subclasses to prevent the popup from hiding when the
// ListView is clicked on (e.g when the list cells have checkboxes).
protected boolean isHideOnClickEnabled() {
return true;
}
which is used on listview:
_listView.addEventFilter(MouseEvent.MOUSE_RELEASED, t -> {
// RT-18672: Without checking if the user is clicking in the
// scrollbar area of the ListView, the comboBox will hide. Therefore,
// we add the check below to prevent this from happening.
EventTarget target = t.getTarget();
if (target instanceof Parent) {
List<String> s = ((Parent) target).getStyleClass();
if (s.contains("thumb")
|| s.contains("track")
|| s.contains("decrement-arrow")
|| s.contains("increment-arrow")) {
return;
}
}
if (isHideOnClickEnabled()) {
comboBox.hide();
}
});
So the behavior you want can be (and probably should be) implemented with custom skin. However, the workaround can be
combobox.setSkin( new ComboBoxListViewSkin<CustomItem>( combobox )
{
@Override
protected boolean isHideOnClickEnabled()
{
return false;
}
} );
and manually hide the popup, when the value is changed for instance:
combobox.valueProperty().addListener( new ChangeListener()
{
@Override
public void changed( ObservableValue observable, Object oldValue, Object newValue )
{
combobox.hide();
}
});
Note please, I didn't fully test this anonymous inner skin approach.
Answered By - Uluk Biy