Reputation: 1080
I'm having issues with positioning and direction when programmatically opening a combo box from withing a table row. Because the combo box is within a table row in a table the user would have to click a total of three times in one cell to open the combo box. For convenience I've created a custom class that allows for one click editing of the combo box. This works wonderfully! However when the combo box opens the top left corner of the resulting dialogue is tucked into the top left corner of the selected cell and not just below and aligned with the combo box. Eg:
This issue corrects itself when the user scrolls the combo box either by using the mouse wheel or by clicking on the scroll bar and moving it.
Another interesting issue is that the combo box will not always open in the correct direction. In one particular table at the bottom of my UI the combo box will open downwards in rows one through five. In rows four and five, once the user scrolls, the combo box will move to the correct position above the combo box. Example of the combo box showing in row 4:
Is there any way I can align the combo box correctly after I've run the combobox.show()
command? Not all of my combo boxes have enough items in them to scroll so programmatically scrolling the combo box will not work for all of my combo boxes.
Here is my custom tablecell class.
private class MyCustomComboBoxTableCell extends TableCell<MyCustomRow, String>{
private final ComboBox<String> comboBox;
public MyCustomComboBoxTableCell(ObservableList<String> items){
this.comboBox = new ComboBox<String>(items);
comboBox.setOnShown(new EventHandler<Event>(){
@Override
public void handle(Event event) {
getTableView().edit(getIndex(), getTableColumn());
getTableView().getSelectionModel().clearSelection();
}
});
comboBox.valueProperty().addListener(new ChangeListener<String>(){
@Override
public void changed(ObservableValue obs, String oldValue, String newValue) {
if(newValue != null && !newValue.equals(oldValue)){
commitEdit(comboBox.getSelectionModel().getSelectedItem());
}
}
});
addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>(){
@Override
public void handle(MouseEvent event){
if(getIndex() < getTableView().getItems().size()){
startEdit();
comboBox.show();
}
}
});
}
@Override
public void startEdit(){
super.startEdit();
setGraphic(comboBox);
setText(null);
}
@Override
public void cancelEdit(){
super.cancelEdit();
setText((String)getItem());
setGraphic(null);
}
@Override
public void updateItem(String item, boolean empty){
super.updateItem(item, empty);
if(empty){
setGraphic(null);
} else {
if(isEditing()){
setGraphic(comboBox);
setText(null);
} else {
setGraphic(null);
setText(getItem());
}
}
}
}
Upvotes: 0
Views: 977
Reputation: 82461
The ComboBox
has not been layouted when you start the edit. The popup will be shown based on the current bounds of the ComboBox
, which means those bounds will most likely be wrong.
Triggering a layout pass on the TableView
should fix this issue:
addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (getIndex() < getTableView().getItems().size()) {
startEdit();
// trigger layout pass
getTableView().applyCss();
getTableView().layout();
comboBox.show();
}
}
});
Upvotes: 1