【问题标题】:Checkbox and ComboBox javaFX [closed]复选框和组合框 javaFX [关闭]
【发布时间】:2019-02-27 07:05:01
【问题描述】:

我想知道,哪些复选框被选中,哪些未被选中。 此外,我想了解如何在 ChomboBox、E.G. 中添加标签。有数字可供选择,1-9有标题“弱”,10-20有标题“强”,但只能从数字中选择,不能从标题中选择。

感谢您的建议

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);

    }
}

【问题讨论】:

标签: java javafx checkbox combobox


【解决方案1】:

我会使用 ListCell 来修改 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);
    });

对于您的其他问题,有多个选项可用于获取选中和未选中复选框的方法。最简单的方法是将您的 CheckBoxes 添加到 Array 和循环中。根据具体需求,还有许多其他方法可以实现这一目标。如果您添加更多详细信息,我可能会尽力提供帮助。

【讨论】:

  • 总是欢迎帮助 :) 只是:这不完全是想要做的 - 没有理由在选择更改时重置 buttonCell。相反,只需设置一次 buttonCell 并让内部组件发挥作用。
  • 感谢您的澄清。您建议如何设置 buttonCell 以避免重置它?
【解决方案2】:

我可能不确定,但如果我正确理解您的问题,您希望将组合框中的数字与标题分组,并让用户使用复选框来选择它们。您还可以找到选择了哪些数字。

如果这是您的问题,正如@Daniel 建议的那样,您必须使用 ListCell 来修改单元格中的内容。首先,我建议为组合框设置一个单独的模型来处理选择。这比检查所选项目的所有 CheckBox 更容易处理。

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

为了实现 CheckBox,您可以使用 CheckBoxListCell,但由于您需要额外的要求来显示组标题,所以这可能不正确。所以我建议根据需求创建自定义单元工厂。

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

您需要考虑的另一个步骤是关闭单击任何单元格时弹出的自动隐藏功能。这将允许您在不关闭弹出窗口的情况下进行多项选择。

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 中的项目并检查模型的选定值。

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

考虑到以上所有,根据我对问题的理解,下面是一个工作演示。

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);
        }
    }
}

【讨论】:

  • 远射,但很好 :) 通常(略多于)挑剔:永远不会在 updateItem 中重新创建控件。并且想知道在通过键盘导航打开的弹出窗口时会发生什么:它们不会跳过标签,或者是吗?
  • 当然应该手动处理鼠标和键事件以禁用标题项。认为在演示中包含该逻辑会使理解实际答案变得过于复杂。
  • 同意,一切都好,您可以考虑添加一个说明,这不是故事的结尾:)
猜你喜欢
  • 2014-12-25
  • 2020-04-01
  • 2011-12-28
  • 1970-01-01
  • 1970-01-01
  • 2019-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多