Sunflame
Sunflame

Reputation: 3186

JavaFx: ComboBox editor's text

I am using the comboBox suggested in this answer: JavaFx: show DatePicker, but I have a problem displaying the correct text. If I chose a date from DatePicker I tried to set the editor's text but it happens nothing. This is what I have tried:

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();
        }
    }
});

After experimenting a lot I added two events to the editor's textProperty and setOnMouseClicked like this:

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

First is not triggered if I don't set manually getEditor().setText(); even if I change the value of the comboBox, that is a little bit weird for me, because I thought this textField holds the text of the comboBox.(maybe am I wrong??). The mouseClick event displays every time an empty string if that line is removed. If the getEditor().setText(); line is there the editor's getText() returns the correct text but it is not displayed in comboBox.

The questions:

I assume that maybe I did somewhere a mistake so that's why this is not working, but I have no idea what, can you help me?

Upvotes: 0

Views: 1275

Answers (2)

Dmytro Maslenko
Dmytro Maslenko

Reputation: 2297

Regarding your question: where is the comboBox's text stored? In general JavaFX controls are based on MVC architecture where the data is stored in model. Controls just represent model data according to defined converters and automatically reacts on any changes of model.

So, in your case the data is stored in ObservableList items. To have updated combobox you need just to replace the corresponding item by new object.

Note, the combobox already listens the ObservableList and any add/remove/set will be automatically represented on UI side.

Why this code doesn't work:

newValue.setValue(newDate);

Because you change the internal state of an item and ObservableList items doesn't react on such changes. Only the changing of the list will work. @Sedrick proposed correct solution.

See also the related question.

Upvotes: 1

SedJ601
SedJ601

Reputation: 13858

In the linked code

Replace:

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

with:

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

The linked code only changes the date at location zero. In this new code, the date in the appropriate location is changed.

Full Code:

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();
    }
}

Upvotes: 1

Related Questions