【问题标题】:JavaFx: ComboBox editor's textJavaFx:组合框编辑器的文本
【发布时间】:2018-01-08 04:06:06
【问题描述】:

我正在使用此答案中建议的组合框:JavaFx: show DatePicker,但我在显示正确文本时遇到问题。如果我从 DatePicker 中选择一个日期,我会尝试设置编辑器的文本,但它什么也没发生。 这是我尝试过的:

getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) ->{
    if (newValue != null) {
        if (MyTupe.DATE.equals(newValue.getType())) {
            initDatePicker();
            datePicker.valueProperty().addListener((obs, oldDate, newDate) -> {
                newValue.setValue(newDate);
                getEditor().setText(newDate.toString());
                datePopOver.hide();
            });
            StackPane stackPane = new StackPane(datePicker);
            stackPane.setPadding(new Insets(10, 10, 10, 10));

            datePopOver.setContentNode(stackPane);
            datePopOver.show(this);
        } else {
            datePopOver.hide();
        }
    }
});

经过大量试验后,我在编辑器的 textProperty 和 setOnMouseClicked 中添加了两个事件,如下所示:

getEditor().textProperty().addListener((observable, oldValue, newValue) -> {
    System.out.println("Text changed");
});
setOnMouseClicked(event -> {
    System.out.println(getEditor().getText());
});

如果我不手动设置getEditor().setText();,即使我更改了comboBox的值,First也不会触发,这对我来说有点奇怪,因为我认为这个textField保存了comboBox的文本。(也许我错了吗??)。如果删除该行,则每次显示一个空字符串时,mouseClick 事件都会显示。 如果getEditor().setText(); 行存在,则编辑器的 getText() 会返回正确的文本,但不会显示在组合框中。

问题:

  • comboBox 的文本存储在哪里?
  • 如何更改 selectedItemProperty 侦听器中的文本?

我认为也许我在某个地方做错了,所以这就是为什么这不起作用,但我不知道是什么,你能帮我吗?

【问题讨论】:

  • - ComboBoxes 可以有一个 StringConverter 将它的值转换为显示的文本。 - 使用 onAction 而不是 onMouseClicked 来触发 ComboBox 和 DatePicker 上用户输入的操作。

标签: java javafx combobox javafx-8


【解决方案1】:

在链接代码中

替换:

items.set(0, new ComboBoxNode(newDate, DATE_TYPE));

与:

items.set(customComboBox.getSelectionModel().getSelectedIndex(), new ComboBoxNode(newDate, DATE_TYPE));

链接代码仅更改位置零处的日期。在此新代码中,相应位置的日期已更改。

完整代码:

import java.time.LocalDate;
import java.time.Month;
import java.util.Objects;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.DatePicker;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import org.controlsfx.control.PopOver;

/**
 *
 * @author blj0011
 */
public class JavaFXApplication155 extends Application
{

    private static final String DATE_TYPE = "DATE";

    private class ComboBoxNode {
        private final Object value;
        private final String type;

        private ComboBoxNode(final Object value, final String type) {
            this.value = value;
            this.type = type;
        }

        @Override
        public String toString() {
            return Objects.toString(value);
        }
    }

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

    @Override
    public void start(Stage primaryStage) {
        final ObservableList<ComboBoxNode> items =
                FXCollections.observableArrayList(
                        new ComboBoxNode(LocalDate.now(), DATE_TYPE),
                        new ComboBoxNode(LocalDate.of(2017, Month.APRIL, 15), DATE_TYPE),//Added new date to ComboBox
                        new ComboBoxNode("11:35AM", "TIME"));

        final PopOver datePopOver = new PopOver();
        datePopOver.setTitle("Enter new date");
        datePopOver.setCornerRadius(10);
        datePopOver.setHeaderAlwaysVisible(true);
        //datePopOver.set(true);
        datePopOver.setAutoHide(true);

        final ComboBox<ComboBoxNode> customComboBox = new ComboBox<>(items);


        customComboBox.getSelectionModel().selectedItemProperty().addListener((o, old, newNode) -> {
            if (newNode != null) {
                if (newNode.type.equals(DATE_TYPE)) {
                    final DatePicker datePicker = new DatePicker((LocalDate) newNode.value);
                    datePicker.valueProperty().addListener((obs, oldDate, newDate) -> {
                        items.set(customComboBox.getSelectionModel().getSelectedIndex(), new ComboBoxNode(newDate, DATE_TYPE));//Fixed this line of code
                        datePopOver.hide();
                    });

                    final StackPane stackPane = new StackPane(datePicker);
                    stackPane.setPadding(new Insets(10, 10, 10, 10));

                    datePopOver.setContentNode(stackPane);
                    datePopOver.show(customComboBox);
                } else {
                    datePopOver.hide();
                }
            }
        });

        final FlowPane pane = new FlowPane(customComboBox);
        pane.setPadding(new Insets(10, 10, 10, 10));
        pane.setPrefWidth(400);
        pane.setPrefHeight(300);

        // Show Scene
        final Scene scene = new Scene(pane);
        primaryStage.setTitle("Popup calendar");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

【讨论】:

  • 成功了,实际上我是这样做的:newValue.setDate(newDate);items.set(customComboBox.getSelectionModel().getSelectedIndex(),customComboBox.getselectionModel().getSelecteditem());
【解决方案2】:

关于您的问题:组合框的文本存储在哪里? 一般来说,JavaFX 控件基于 MVC 架构,其中数据存储在模型中。控件仅根据定义的转换器表示模型数据,并自动对模型的任何更改做出反应。

因此,在您的情况下,数据存储在ObservableList items 中。要更新组合框,您只需将相应的项目替换为新对象即可。

请注意,组合框已经监听了ObservableList,并且任何添加/删除/设置都将自动显示在 UI 端。

为什么这段代码不起作用:

newValue.setValue(newDate);

因为您更改了项目的内部状态,而 ObservableList items 不会对此类更改做出反应。只有更改列表才会起作用。 @Sedrick 提出了正确的解决方案。

另见the related question

【讨论】:

    猜你喜欢
    • 2014-07-21
    • 2017-02-11
    • 1970-01-01
    • 2021-05-09
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 2012-12-03
    • 1970-01-01
    相关资源
    最近更新 更多