我正在开发预订系统的界面。在一个窗口中,我需要获取预订的开始时间和所需的预订结束时间,以便检查数据库是否有可用的插槽。 (只有......:感兴趣,我在其他地方得到了一天)。 组合框看起来像这样:
//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);
对于endTime来说是相同的(具有相同组件的HBox只更改了变量名称
我希望我的startTime小时组合框自动禁用那些高于当前endTime组合框小时的项目,反之亦然我希望禁用低于startTime小时组合框的endTime小时项目。 我曾尝试制作一个单元格工厂,但是如果我在编辑其他组合框之前打开组合框就无法工作。
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;
}
});
答案 0 :(得分:1)
您的单元格需要观察另一个组合框中的值,以便它知道如果其中的值发生更改,则更新其禁用状态。
请注意,您还会在单元格实施中遇到其他错误:您必须考虑updateItem()
方法中的所有可能性:例如:您没有正确处理该项为null(该单元格为空),或者在需要时将禁用状态设置为false。最后,在这里使用字符串作为数据类型既不方便(你可能必须在某些时候转换回int来使用这些值)并且弄乱逻辑(因为“10”小于“2”,例如)。你应该在这里使用ComboBox<Integer>
。
这是一个只有两个“小时”组合框的实现:
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);
}
}
答案 1 :(得分:0)
并不复杂但不禁用ComboBox中的项目将仅保留startHours
并使用所选值来确定endHours
中显示的内容。当startHours
值更改时,它将填充endHours
从开始到23的所有小时数。如果已选择endHours
并且您将startHours
更改为更高的值,则赢取什么都不显示,必须重新选择。 startHours
中的值无关紧要,只需更改endHours
中的值。
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);
}
});