true

My problem is I am trying to disable a list item from a combobox selection based on checking whether or not a certain variable is null or not. The combobox values are populated from the class StatusModel.

If a user has not properly uploaded an artwork file saved as a string under the variable filePath then I want to have a combobox list cell be disabled. Once that variable is no longer null or is not empty then I want the option to become available for selection. Currently the code below will show the list item as disabled during initialization but will not update as the variable filePath is changed.

Here is my StatusModel which is used for the combobox data:

    //Status model used to populates the condition or status of an order I.E. complete, not complete
public class StatusModel {
    private final StringProperty statusId;
    private final StringProperty statusName;

    public StatusModel (String orderStatusId, String orderStatusName){
        this.statusId = new SimpleStringProperty(orderStatusId);
        this.statusName = new SimpleStringProperty(orderStatusName);
    }

    public String getStatusId() {return statusId.get();}
    public String getStatusName() {return statusName.get();}
    public StringProperty StatusIdProperty() {return statusId;}
    public StringProperty StatusNameProperty() {return statusName;}
    public void setStatusId(String orderStatusId) {this.statusId.set(orderStatusId);}
    public void setStatusName(String orderStatusName) {this.statusName.set(orderStatusName);}
}

Here is my controller class used which includes my combobox and other elements to better understand the problem:

public class Controller implements Initializable{

    @FXML private JFXComboBox<StatusModel> status;

    private ObservableList<StatusModel> orderStatusModel;   

    private String filePath;


    @Override
    public void initialize(URL location, ResourceBundle resources) {
        this.status.setItems(orderStatusModel);
        this.status.setCellFactory(statusFactory);
        this.status.setButtonCell(statusFactory.call(null));
    }


    private void loadStatusOptions(){
        String SQL = "SELECT image_status_id, image_status_name \n " +
                     "FROM abc_production.image_status \n " +
                     "WHERE image_status_id = 1 OR image_status_id = 2 \n" +
                     "ORDER BY image_status_id ASC; ";

        try {
            Connection connection = DBConnection.getConnection();  //Create a connection to the database
            this.orderStatusModel = FXCollections.observableArrayList();
            ResultSet resultSet = connection.createStatement().executeQuery(SQL);
            while (resultSet.next()){
                this.orderStatusModel.add(new StatusModel(resultSet.getString("image_status_id"), resultSet.getString("image_status_name")));
            }
        } catch (SQLException e){
            System.out.println(e + "Failed at method loadStatusOptions");
        }
    }

    private void uploadFile(){
        File file; 

        FileChooser fileChooser = new FileChooser();

        file = fileChooser.showOpenDialog(getScene().getWindow());

        filePath = file.getAbsolutePath();
    }

    Callback<ListView<StatusModel>, ListCell<StatusModel>> statusFactory = listView -> new ListCell<StatusModel>(){
        @Override
        protected void updateItem(StatusModel item, boolean empty){
            super.updateItem(item, empty);
            if(item != null || !empty){
                setText(empty ? "" : item.getStatusName()); 
                updateDisableState();

            }
        }

        public void updateDisableState(){
            if(getItem().getStatusName().equalsIgnoreCase("pre-edit complete") && filePath != null && !filePath.isEmpty()){
                setDisable(false);
            } else if (getItem().getStatusName().equalsIgnoreCase("pre-edit complete")) {
                setDisable(true);
            } else {
                setDisable(false);
            }
        }
    };  
}

I have searched all over to try to find an answer and I am guessing I just don't know the correct terminology to properly search what I am trying to do. It is almost as if I just need to somehow call the super.updateItem method one more time as a boolean is altered.

Here is one post that I thought I was close to finding an answer: JavaFX 2.2: How to force a redraw/update of a ListView

Any guidance would be great!

upvote
  flag
don't use refresh as suggested in the other answer ... ever! Instead use a observableList with an extractor installed on the property orderstatusName (or better: add a status boolean on OrderStatus that's updated as appropriate - the Order knows best when that's the case - and install the extractor on that boolean). For examples of using extractor, see the api doc of FXCollections (from the top of my head not entirely certain ;) – kleopatra
upvote
  flag
I tried something like that from this post: //allinonescript.com/questions/16880115/… but I seem to be doing something wrong with the extractor.. updating my code above to reflect what I tried but I get an error in the model stating incompatible types: String property cannot be converted to Observable. I will check for more documentation though. Thanks! – user3700865
upvote
  flag
@James_D I will edit my original question. – user3700865
upvote
  flag
@James_D I am trying to refine it here just taking me some time. – user3700865
upvote
  flag
ahh ... just seeing that you want to prevent selection of the disabled item - that's not supported, at least not without lots of work: setting cell disabled will prevent selection by mouse, but not by keyboard. Ideally you would need a custom selectionModel that simply doesn't change the selection if the model (remember: orderStatusModel is the object that decides) vetoes it. But .. custom selectionModels are not loved, and you'll probably (no time to test right now, ... hunger --- :)) need to implement a custom ComboBoxListViewSkin that makes the list aware of the custom selectionModel – kleopatra
upvote
  flag
@James_D I tried to keep the code minimal, other than some format I am working on, I believe it is complete. As far as the editedArtworkLocation variable. It is an indepenent variable that is changed after a user selects a file from a fileChooser. I am trying to figure out how tell the cell that a change occurred and to update the list accordingly. – user3700865
upvote
  flag
@James_D Alright. I will attempt to write another project that better demonstrates the issue. It seems I need to clarify how the editedArtworkLocation variable gets updated. I will spend some more time on this and update soon. – user3700865
upvote
  flag
Tough crowd... well.. for what is it worth.. I did revise my post once again trying to create a MVCE to illustrate the problem. – user3700865
upvote
  flag
@kelopatra thanks for your suggestions I will look into combobox listview skin and see what I can come up with. – user3700865
1 upvote
  flag
Would it suffice to add/remove the relevant items from the combo box as needed, instead of disabling their cells? That could be done very easily, using a filtered list. – James_D
upvote
  flag
I would rather not go that direction as I want the options to be visible but... I am not sure this is possible at this point. I might just have to show the combobox items and prevent the user from switching until a value can be seen from filePath – user3700865
upvote
  flag
after a night of sleep I would follow @James_D - rethink the UX. Why do you want items in the combo that are not selectable? What should the user do with such an unselectable item? Is there any standard app that's doing it and if so, what is its exact behaviour? – kleopatra
upvote
  flag
I want the user to know of available options but not be allowed to access an option without fulfilling a prerequisite. I believe this is fairly common in UIs. Just the way I am going about it is more than likely flawed and not good UI design. I just need a file imported into a database before a user can move an order through to the next stages. filePath in my MVCE above is that prerequisite. Once that contains a value a user is allowed to move the order along through. – user3700865

0 Answers 11

Not the answer you're looking for? Browse other questions tagged or ask your own question.