Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaFX更新组合框项目列表,以基于可变输入禁用某些项目_Java_Javafx_Combobox - Fatal编程技术网

JavaFX更新组合框项目列表,以基于可变输入禁用某些项目

JavaFX更新组合框项目列表,以基于可变输入禁用某些项目,java,javafx,combobox,Java,Javafx,Combobox,我正在为预订系统开发一个界面。在一个窗口中,我需要获得预定的开始时间和预定的结束时间,以便检查db是否有该时段可用。只有hh:嗯,我有兴趣,我在其他地方得到了这一天。 组合框如下所示: //startTime HBox HBox startTime = new HBox(); startTime.setSpacing(5); final ComboBox startHours = new ComboBox(hours); final ComboBox startM

我正在为预订系统开发一个界面。在一个窗口中,我需要获得预定的开始时间和预定的结束时间,以便检查db是否有该时段可用。只有hh:嗯,我有兴趣,我在其他地方得到了这一天。 组合框如下所示:

//startTime HBox
    HBox startTime = new HBox();
    startTime.setSpacing(5);
    final ComboBox startHours = new ComboBox(hours);
    final ComboBox startMinutes = new ComboBox(minutes);
    final Label colon = new Label(":");
    startTime.getChildren().addAll(startHours,colon,startMinutes);
endTimean HBox的情况也一样,它的组件相同,只是变量名发生了变化

我希望startTime-hour组合框自动禁用高于当前endTime组合框小时数的项目,反之亦然,我希望禁用低于startTime-hour组合框的endTime-hour项目。 我曾经尝试创建一个单元格工厂,但是如果我在编辑另一个组合框之前打开组合框,它就不起作用了

startHours.setCellFactory(
    new Callback<ListView<String>, ListCell<String>>() {
            @Override 
            public ListCell<String> call(ListView<String> param) {
                final ListCell<String> cell = new ListCell<String>() {

                    @Override public void updateItem(String item, 
                        boolean empty) {
                            super.updateItem(item, empty);
                            if (item!=null){
                                setText(item);
                            }
                            if ((endHours.getValue()!=null) && (endHours.getValue().toString().compareTo(item)<0)){
                                setDisable(true);
                                setStyle("-fx-background-color: #ffc0cb");
                            }
                        }
            };
            return cell;
        }
    });

您的单元格需要观察另一个组合框中的值,以便在该组合框中的值发生更改时知道如何更新其禁用状态

注意,单元格实现中还有其他错误:您必须考虑updateItem方法中的所有可能性:例如,您没有正确处理项目为null、单元格为空,或者在需要时将禁用状态设置回false。最后,在这里使用字符串作为数据类型既不方便,又可能需要在某个时候转换回int来使用这些值,并且会弄乱逻辑,例如,因为10小于2。你应该在这里使用组合框

下面是一个仅包含两个小时组合框的实现:

import java.util.function.BiPredicate;

import javafx.application.Application;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;


public class DependentComboBoxes extends Application {

    private ComboBox<Integer> startHours ;
    private ComboBox<Integer> endHours ;

    @Override
    public void start(Stage primaryStage) {
        startHours = new ComboBox<>();
        endHours = new ComboBox<>();
        startHours.setCellFactory(lv -> new StartHoursCell());
        endHours.setCellFactory(lv -> new EndHoursCell());
        for (int i = 0; i < 24 ; i++) {
            startHours.getItems().add(i);
            endHours.getItems().add(i);
        }

        GridPane root = new GridPane();
        root.setHgap(5);
        root.setVgap(5);
        root.addRow(0, new Label("Start hours:"), startHours);
        root.addRow(1, new Label("End hours:"), endHours);

        root.setAlignment(Pos.CENTER);
        root.setPadding(new Insets(20));
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }

    private class StartHoursCell extends ListCell<Integer> {

        StartHoursCell() {
            endHours.valueProperty().addListener((obs, oldEndHours, newEndHours) -> updateDisableState());
        }

        @Override
        protected void updateItem(Integer hours, boolean empty) {
            super.updateItem(hours, empty);
            if (empty) {
                setText(null);
            } else {
                setText(hours.toString());
                updateDisableState();
            }
        }

        private void updateDisableState() {
            boolean disable = getItem() != null && endHours.getValue() != null && 
                    getItem().intValue() > endHours.getValue();
            setDisable(disable) ;
            setOpacity(disable ? 0.5 : 1);
        }
    }

    private class EndHoursCell extends ListCell<Integer> {

        EndHoursCell() {
            startHours.valueProperty().addListener((obs, oldEndHours, newEndHours) -> updateDisableState());
        }

        @Override
        protected void updateItem(Integer hours, boolean empty) {
            super.updateItem(hours, empty);
            if (empty) {
                setText(null);
            } else {
                setText(hours.toString());
                updateDisableState();
            }
        }

        private void updateDisableState() {
            boolean disable = getItem() != null && startHours.getValue() != null && 
                    getItem().intValue() < startHours.getValue();
            setDisable(disable) ;
            setOpacity(disable ? 0.5 : 1);

        }
    }

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

没有那么复杂,但不禁用组合框中的项目将是单独保留startHours,并使用所选的值来确定endHours中显示的内容。当startHours值更改时,它将用从开始到23的所有小时填充endHours。如果已经选择了endHours,并且您将startHours更改为更高的值,那么它将不会显示任何内容,并且必须重新选择。startHours中的值不应该改变,只是endHours中的值


这是一个非常令人惊讶的答案,詹姆斯·D。。这将对我有很大帮助…同时,我在操作事件的提交按钮中进行了一些错误检查,因为我认为这种方法太复杂了。然而,你的回答证明这并不难。但愿有人在我旁边解释听众和事件之间的区别:d同时,非常感谢
ComboBox<Integer> start = new ComboBox<Integer>();
ComboBox<Integer> end = new ComboBox<Integer>();
for(int i : IntStream.range(1, 24).toArray()) {
    start.getItems().add(i);
    end.getItems().add(i);
}
start.setOnAction(ae -> {
    Integer selected = end.getSelectionModel().getSelectedItem();
    end.getItems().clear();
    for(int i : IntStream.range(start.getSelectionModel().getSelectedItem(), 24).toArray()) {
        end.getItems().add(i);
    }
    if(end.getItems().contains(selected)) {
        end.getSelectionModel().select(selected);
    }
});