我有带有页码(1、2、3等)的组合框。当用户选择特定页面时(通过鼠标或键盘(组合框可编辑))。我要显示和总计页面。这就是为什么我在组合框操作中也会这样做的原因:

combobox.setValue(currentPage+"/"+totalPages)


所以最终的代码看起来像

   @FXML
    private void onPageComboBoxAction(ActionEvent event){
       ....
       combobox.setValue(currentPage+"/"+totalPages)
    }


但是,此代码又触发了一个ActionEvent和代码周期。因此,我看到了两种可能的方法:


处理一些特定事件(但是哪些以及如何处理)
寻找在不触发另一个事件的情况下更改组合框值的方法(再次如何?)


谁能帮我解决这个问题?

最佳答案

setValue(...)更改组合框保存的值(即,它更改数据或基础模型的状态)。在我看来,您真正想要的只是改变数据的显示方式。您可以通过设置按钮单元格来更改所选值的显示。

这是一个示例,其中按钮单元格同时跟踪所选项目和页面数:

import java.util.Random;
import java.util.stream.IntStream;

import javafx.application.Application;
import javafx.collections.ListChangeListener.Change;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class PageNumberCombo extends Application {

    private static final Random RNG = new Random();

    @Override
    public void start(Stage primaryStage) {
        ComboBox<Integer> combo = new ComboBox<>();
        combo.setButtonCell(new ListCell<Integer>() {
            {
                itemProperty().addListener((obs, oldValue, newValue) -> update());
                emptyProperty().addListener((obs, oldValue, newValue) -> update());
                combo.getItems().addListener((Change<? extends Integer> c) -> update());
            }

            private void update() {
                if (isEmpty() || getItem() == null) {
                    setText(null);
                } else {
                    setText(String.format("%d / %d", getItem().intValue(), combo.getItems().size()));
                }
            }
        });

        Button reloadButton = new Button("Reload");
        reloadButton.setOnAction(e -> reload(combo));

        reload(combo);

        HBox root = new HBox(10, combo, reloadButton);
        root.setAlignment(Pos.CENTER);
        root.setPadding(new Insets(24));
        primaryStage.setScene(new Scene(root, 240, 60));
        primaryStage.show();
    }

    private void reload(ComboBox<Integer> combo) {
        int numPages = RNG.nextInt(10) + 11 ;
        combo.getItems().clear();
        IntStream.rangeClosed(1, numPages).forEach(combo.getItems()::add);
    }

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


如果您的ComboBox是可编辑的,则默认情况下按钮单元格是TextField,组合框的converter用于将文本字段中的字符串值转换为模型值,反之亦然。因此,在这种情况下,您只需要安装一个在整数x和字符串"x / total"之间转换的转换器。

请注意,默认情况下,此转换器还用于在下拉列表的单元格中显示文本,因此,如果希望这些文本显示为整数值,则需要安装cellFactory来显式创建这些单元格。

import java.util.Random;
import java.util.stream.IntStream;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.StringConverter;

public class PageNumberCombo extends Application {

    private static final Random RNG = new Random();

    @Override
    public void start(Stage primaryStage) {
        ComboBox<Integer> combo = new ComboBox<>();

        combo.setEditable(true);
        combo.setConverter(new StringConverter<Integer>() {

            @Override
            public String toString(Integer object) {
                return object + " / " + combo.getItems().size();
            }

            @Override
            public Integer fromString(String string) {
                int index = string.indexOf('/');
                if (index < 0) {
                     index = string.length();
                }
                String text = string.substring(0, index).trim();
                try {
                    return Integer.parseInt(text);
                } catch (Exception exc) {
                    return 0 ;
                }
            }

        });

        combo.setCellFactory(lv -> new ListCell<Integer>() {
            @Override
            public void updateItem(Integer item, boolean empty) {
                super.updateItem(item, empty);
                if (empty) {
                    setText(null) ;
                } else {
                    setText(item.toString());
                }
            }
        });

        Button reloadButton = new Button("Reload");
        reloadButton.setOnAction(e -> reload(combo));

        reload(combo);

        HBox root = new HBox(10, combo, reloadButton);
        root.setAlignment(Pos.CENTER);
        root.setPadding(new Insets(24));
        primaryStage.setScene(new Scene(root, 240, 60));
        primaryStage.show();
    }

    private void reload(ComboBox<Integer> combo) {
        int numPages = RNG.nextInt(10) + 11 ;
        combo.getItems().clear();
        IntStream.rangeClosed(1, numPages).forEach(combo.getItems()::add);
    }

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

10-07 23:42