在 ComboBox 中设置自定义值

Set custom value in ComboBox

我有 ComboBox,我想用它来配置服务延迟时间:

import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import javafx.util.Duration;

public class MainApp extends Application
{
    public static void main(String[] args)
    {
        launch(args);
    }

    private MyService myService = new MyService();

    @Override
    public void start(Stage stage)
    {
        myService.setDelay(new Duration(300));
        myService.setPeriod(new Duration(1000));

        myService.start();
        stage.setTitle("ComboBoxSample");
        Scene scene = new Scene(new Group(), 450, 250);

        ComboBox emailComboBox = new ComboBox();
        emailComboBox.getItems().addAll("Stop", "1 Second", "5 Seconds", "10 Seconds", "15 Seconds");
        emailComboBox.setPromptText("Email address");
        emailComboBox.valueProperty().addListener(new ChangeListener<String>()
        {
            @Override
            public void changed(ObservableValue ov, String t, String t1)
            {
                if (t1.equals("Stop"))
                {
                    myService.cancel();
                }
                if (t1.equals("1 Second"))
                {
                    myService.setPeriod(new Duration(1000));
                }
                if (t1.equals("5 Second"))
                {
                    myService.setPeriod(new Duration(5000));
                }
                if (t1.equals("10 Second"))
                {
                    myService.setPeriod(new Duration(10000));
                }
                if (t1.equals("15 Second"))
                {
                    myService.setPeriod(new Duration(15000));
                }
            }
        });

        GridPane grid = new GridPane();
        grid.setVgap(4);
        grid.setHgap(10);
        grid.setPadding(new Insets(5, 5, 5, 5));
        grid.add(new Label("To: "), 0, 0);
        grid.add(emailComboBox, 1, 0);

        Group root = (Group) scene.getRoot();
        root.getChildren().add(grid);
        stage.setScene(scene);
        stage.show();
    }
}

有没有什么巧妙的方法可以减少我用来设置服务延迟期的太多 if() 开关案例。 我想添加 emailComboBox.setEditable(true); 并根据我的自定义输入设置服务延迟时间。

由于用户实际上选择了 Duration,因此 ComboBox 的数据类型应该是 Duration,而不是 String。安装单元工厂以配置 Duration 对象在组合框中的显示方式:

    ComboBox<Duration> combo =  new ComboBox<>(
            FXCollections.observableArrayList(
                Duration.UNKNOWN,
                Duration.seconds(1),
                Duration.seconds(5),
                Duration.seconds(10),
                Duration.seconds(15)));

    combo.setCellFactory(lv -> createListCell());
    combo.setButtonCell(createListCell());

    combo.valueProperty().addListener((obs, oldValue, newValue) -> {
        if (newValue == null || newValue == Duration.UNKNOWN) {
            myService.cancel();
        } else {
            myService.setPeriod(newValue);
        }
    });

自定义单元实现类似于

private ListCell<Duration> createListCell() {
    return new ListCell<Duration>() {
       @Override
       public void updateItem(Duration item, boolean empty) {
           super.updateItem(item, empty);
           if (empty) {
               setText(null);
           } else {
               if (item == Duration.UNKNOWN) {
                   setText("Stop");
               } else {
                   setText(String.format("%.0f Second", item.toSeconds()));
               }
           }
       }
    };
}