0

I've inherited some code that I'm trying to extend by changing the border color of a ComboBox based on a detected ComboBox value change. However, it seems that any changes made to the ComboBox style do not make it outside of the ChangeListener lambda.

Basically, the ComboBox border is initialized to black and I want to change to color after the user changes the value, but the color set inside the ChangeListener doesn't get applied. When I step through the code I see the style string change inside the lambda ChangeListener, but it goes back to the initial style string when I exit the lambda ChangeListener.

I've included the code I'm modifying below, with the code I'm trying to add set the ComboBox style inserted and called out. Any help would be appreciated.

public class SearchScreenController 
{
    @FXML
    private TableView<ConfigBaselineFileArtifact> searchRecordsTable;
    @FXML 
    private TableColumn<ConfigBaselineFileArtifact, String> categoryColumn = new TableColumn<>("File Category");
    @FXML 
    private TableColumn<ConfigBaselineFileArtifact, ConfigBaselineFileArtifact> subcategoryColumn = new TableColumn<>("File Subcategory")

    private void createSearchTable() 
    {
        searchRecordsTable.getColumns().clear();

        //File Category and Subcategory Columns
        categoryColumn.setCellValueFactory(new PropertyValueFactory<>("fileCategoryName"));
        subcategoryColumn.setCellValueFactory(value -> new SimpleObjectProperty(value.getValue()));

        categoryColumn.setCellFactory(param -> new TableCell<ConfigBaselineFileArtifact, String>() {
                @Override
                protected void updateItem(String item, boolean empty) {
                    super.updateItem(item, empty);
                    if (!empty) {
                        ComboBox<String> cb = new ComboBox<String>(FXCollections.observableArrayList(categoryList));
                        cb.setValue(item);
                        cb.setPrefWidth(145);
                        cb.setStyle("-fx-background-color: transparent; -fx-border-color: black;");

                        cb.getSelectionModel().selectedItemProperty().addListener((ChangeListener<String>) (observable, oldValue, newValue) -> {
                            if (newValue != null) {
                                int index = getIndex();
                                // Test for case that updated combobox isn't listed with list of selected records
                                if (!searchRecordsTable.getSelectionModel().getSelectedIndices().contains(index)) {
                                    searchRecordsTable.getItems().get(index).setFileCategoryName(newValue);
                                    searchRecordsTable.getItems().get(index).setFileSubCategoryName("");
                                    DataStore.getInstance().saveConfigBaselineFileArtifact(searchRecordsTable.getItems().get(index));
                                } else {
                                    // Else if updated combobox IS within list of selected records
                                    searchRecordsTable.getSelectionModel().getSelectedItems().forEach(record -> {
                                        record.setFileCategoryName(newValue);
                                        record.setFileSubCategoryName("");
                                        DataStore.getInstance().saveConfigBaselineFileArtifact(record);
                                    });
                                }

                                // Code I'm trying to add is below
                                if (newValue.equals("")) {
                                    cb.setStyle("-fx-background-color: transparent; -fx-border-color: red;");
                                } else {
                                    cb.setStyle("-fx-background-color: transparent; -fx-border-color: green;");
                                // Code I'm trying to add is above

                                searchRecordsTable.refresh();                                    
                            }
                        });
                        setGraphic(cb);
                    }
                }
            });
        searchRecordsTable.getColumns().addAll(checkBoxColumn, fileNameColumn, artifactNameColumn, categoryColumn, subcategoryColumn, sensorNameColumn, subsystemColumn, componentColumn, dateImportedColumn, importedByColumn, labelsColumn);
        searchRecordsTable.refresh();
        searchRecordsTable.setEditable(true);
        searchRecordsTable.getSelectionModel().getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
    }
}
Curtis
  • 3
  • 3
  • Also the border is hard to see, if you don't increase the size, since `ComboBox` doesn't use one by default, so the resulting border is just 1 px wide... – fabian Jul 06 '18 at 14:33
  • Also this won't restore the look same look when the item is moved to another cell. Furthermore cells becoming empty will keep the `ComboBox` as `graphic`. Also you're recreating the `ComboBox` every time the item is replaced... – fabian Jul 06 '18 at 14:38
  • @fabian I'm sorry, I don't understand what linked string comparison question has to do with setting the ComboBox style inside the. Perhaps you were referencing how I was using `newValue == ""` instead of `newValue.equals("")`? – Curtis Jul 06 '18 at 15:10

1 Answers1

0

I think the problem is, that the border is being reset on your searchRecordsTable.refresh(); call. It seems that the updateItem(String item, boolean empty) function is called again. You need to make sure, that you store the state anywhere else, e.g. a HashMap. Something like this:

private Map<String, Boolean> changeMap = new HashMap<>();
//in your selectedItem listener
if (newValue.equals("")) {
    changeMap.remove(item);
} else {
    changeMap.put(item, true);
}
//before setGraphic(cb)
if(changeMap.contains(item)) {
    cb.setStyle("-fx-background-color: transparent; -fx-border-color: green;");
}
Halko Karr-Sajtarevic
  • 2,248
  • 1
  • 16
  • 14