0

i'd like to find out, which CheckBoxes are checked and which are unchecked by one method. Furthermore, i'd like to find out how can i add label in ChomboBox, E.G. there are numbers to choose, and from 1-9 there is heading "weak",from 10-20 there is heading "strong", but you can choose only from numbers and not from headings.

Thanks for any suggestion

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.text.Font;

import java.net.URL;
import java.util.ResourceBundle;

public class Controller implements Initializable {
    public Label l1,l2,l3,l4,l5,l6,l7,l8;
    public Button generovatB;
    public TextField jtxt1;
    public ComboBox cbox1;
    public CheckBox cb1,cb2,cb3,cb4,cb7;
    public Font x2;
    public ImageView imgvBck;
    //created by Z.K. =
    private char[] lower = {'a','b','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
    private char[] upper = {'A','B','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
    private char[] special = {'#','&','@','{','}','[',']','+','-','*','/','?','.',':','!','§',')','(','/','%','=',';','<','>','ß','$'};
    private char[] numbers = {'1','2','3','4','5','6','7','8','9','0'};
    private String[] words = new String[1000];



    public void generovatB(ActionEvent actionEvent) {


    }


    public void naplnPole(){


}

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        Image pozadi = new Image("obr.png",650,500,true,false,false);
        imgvBck.setImage(pozadi);
        ObservableList<String> options =
                FXCollections.observableArrayList("5","7","9","15","18"
                );
        cbox1.setItems(options);

    }
}
  • a) loop through them and check whether they are b) read a decent tutorial on how stuff is done on combo (f.i. https://docs.oracle.com/javase/8/javafx/user-interface-tutorial/index.html) – kleopatra Sep 23 '18 at 16:31
  • cb1.getSelected() will return true if the CheckBox object is toggled on. – faris Sep 23 '18 at 17:23
  • This is probably what you need. https://stackoverflow.com/questions/32424915/how-to-get-selected-radio-button-from-togglegroup – rizcan Sep 23 '18 at 18:47
  • @rizcan *"i'd like to find out, which CheckBoxes are checked"* the use of plural here indicates that no `ToggleGroup` is used (or could be used) in the code. – fabian Sep 24 '18 at 18:07

2 Answers2

1

May be I am not sure, but if I understand your question correctly, you want to group the numbers in the combo box with a heading, and let the user to select them using checkboxes. And also you to find which numbers are selected.

If this is your question, as @Daniel suggested you have to use a ListCell to modify the content in the cell. Firstly, I would recommend to have a separate model for the combo box to handle the selection. This would make things much easier to handle than checking through all CheckBoxes for the selected items.

class Level {
        private IntegerProperty level = new SimpleIntegerProperty();
        private BooleanProperty selected = new SimpleBooleanProperty();
        ...
}

For implementing CheckBox, you can go with CheckBoxListCell but as you need an extra requirement to show the group heading, this may not suite correctly. So I would suggest to create custom cell factory for the requirements.

// Implementing with CheckBoxListCell
Callback<ListView<Level>, ListCell<Level>> forListView = CheckBoxListCell.forListView(Level::selectedProperty);
comboBox.setCellFactory(forListView);

Another step you need to consider is to turn off the auto hide feature of popup on click of any cell. This will allow you to do multiple selection without closing the pop up.

final ComboBox<Level> comboBox = new ComboBox<Level>(items) {
            protected javafx.scene.control.Skin<?> createDefaultSkin() {
                return new ComboBoxListViewSkin<Level>(this) {
                    @Override
                    protected boolean isHideOnClickEnabled() {
                        return false;
                    }
                };
            }
        };

To find the selected numbers, all you have to do is loop through the items in the ComboBox and check the selected value of the model.

comboBox.getItems().stream().filter(Level::isSelected).forEach(selectedItem->{
      // Do with your selected item
});

Considering all the above, below is a working demo as per my understanding of the question. enter image description here

import com.sun.javafx.scene.control.skin.ComboBoxListViewSkin;
import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Callback;

import java.util.stream.Collectors;

public class HeadingInComboBoxDemo extends Application {

    private final int WEAK_INDEX = -1;
    private final int STRONG_INDEX = -2;

    @Override
    public void start(Stage stage) throws Exception {
        VBox root = new VBox();
        root.setSpacing(15);
        root.setPadding(new Insets(25));
        root.setAlignment(Pos.TOP_LEFT);
        Scene sc = new Scene(root, 600, 600);
        stage.setScene(sc);
        stage.show();

        final ObservableList<Level> items = FXCollections.observableArrayList();
        for (int i = 1; i < 11; i++) {
            if (i == 1) {
                items.add(new Level(WEAK_INDEX));
            } else if (i == 6) {
                items.add(new Level(STRONG_INDEX));
            }
            items.add(new Level(i));
        }

        final ComboBox<Level> comboBox = new ComboBox<Level>(items) {
            protected javafx.scene.control.Skin<?> createDefaultSkin() {
                return new ComboBoxListViewSkin<Level>(this) {
                    @Override
                    protected boolean isHideOnClickEnabled() {
                        return false;
                    }
                };
            }
        };
        comboBox.setPrefWidth(150);
        comboBox.setItems(items);
        comboBox.setCellFactory(new Callback<ListView<Level>, ListCell<Level>>() {
            @Override
            public ListCell<Level> call(ListView<Level> param) {
                return new ListCell<Level>() {
                    private CheckBox cb = new CheckBox();
                    private BooleanProperty booleanProperty;

                    {
                        cb.setOnAction(e->getListView().getSelectionModel().select(getItem()));
                    }
                    @Override
                    protected void updateItem(Level item, boolean empty) {
                        super.updateItem(item, empty);
                        if (!empty) {
                            if (item.getLevel() == WEAK_INDEX || item.getLevel() == STRONG_INDEX) {
                                Label lbl = new Label(item.getLevel() == WEAK_INDEX ? "Weak" : "Strong");
                                lbl.setStyle("-fx-font-size:14px;-fx-font-weight:bold;");
                                setGraphic(lbl);
                                setText(null);
                            } else {
                                if (booleanProperty != null) {
                                    cb.selectedProperty().unbindBidirectional(booleanProperty);
                                }
                                booleanProperty = item.selectedProperty();
                                cb.selectedProperty().bindBidirectional(booleanProperty);
                                setGraphic(cb);
                                setText(item.getLevel() + "");
                            }
                        } else {
                            setGraphic(null);
                            setText(null);
                        }
                    }
                };
            }
        });

        comboBox.setButtonCell(new ListCell<Level>() {
            @Override
            protected void updateItem(Level item, boolean empty) {
                super.updateItem(item, empty);
                String selected = comboBox.getItems().stream().filter(i -> i.isSelected())
                        .map(i -> i.getLevel()).sorted()
                        .map(i -> i + "").collect(Collectors.joining(","));
                setText(selected);
            }
        });

        Text txt = new Text();
        Button show = new Button("Show Selected");
        show.setOnAction(e->{
            StringBuilder sb = new StringBuilder();
            comboBox.getItems().stream().filter(Level::isSelected).forEach(item->{
                sb.append(item.getLevel()).append("\n");
            });
            txt.setText(sb.toString());
        });

        root.getChildren().addAll(comboBox,show,txt);
    }

    public static void main(String[] args) {
        Application.launch(args);
    }

    class Level {
        private IntegerProperty level = new SimpleIntegerProperty();
        private BooleanProperty selected = new SimpleBooleanProperty();

        public Level(int level) {
            setLevel(level);
        }

        public int getLevel() {
            return level.get();
        }

        public IntegerProperty levelProperty() {
            return level;
        }

        public void setLevel(int level) {
            this.level.set(level);
        }

        public boolean isSelected() {
            return selected.get();
        }

        public BooleanProperty selectedProperty() {
            return selected;
        }

        public void setSelected(boolean selected) {
            this.selected.set(selected);
        }
    }
}
Sai Dandem
  • 8,229
  • 11
  • 26
  • long shot, but nice :) the usual (slightly more than) nit-pick: never-ever re-create controls in updateItem. And wondering what happens on navigating the open popup by keyboard: they don't jump over the labels, or do they? – kleopatra Sep 24 '18 at 09:02
  • Ofcourse handling Mouse and Key events to disable the Heading item should be handled manually. Thought that including that logic in demo makes it too complex to understand the actual answer. – Sai Dandem Sep 24 '18 at 11:31
  • Agreed, all fine, you might consider to add a note that this isn't the end of the story :) – kleopatra Sep 24 '18 at 11:38
0

I would use ListCell to modify the text in ComboBox:

cbox1.getSelectionModel().selectedItemProperty().addListener((ObservableValue< ? extends String> observable, String oldValue, String newValue) -> {
        ListCell<String> lc = new ListCell<>();
        if (Integer.valueOf(newValue) < 10) {
            lc.setText("Weak (" + newValue + ")");
        } else if (Integer.valueOf(newValue) < 21) {
            lc.setText("Strong (" + newValue + ")");
        } else {
            lc.setText("");
        }
        cbox1.setButtonCell(lc);
    });

For your other question, there are multiple options for a method that get selected and unselected checkboxes. The simplest is to add your CheckBoxes to an Array and loop. Depending on specific needs there are many other ways to achieve this. If you add more details I may try to help.

Oboe
  • 2,643
  • 2
  • 9
  • 17
  • help always welcome :) just: this is not exactly what want to do - there's no reason to reset the buttonCell whenever the selection changes. Instead, set the buttonCell once and let internals do its magic. – kleopatra Sep 24 '18 at 08:52
  • Thanks for the clarification. How would you suggest setting the buttonCell to avoid reseting it? – Oboe Sep 26 '18 at 18:09