将枚举的 toString() 绑定到标签

Binding an enum's toString() to a Label

我已将我的应用程序设置为根据枚举更改其功能。链接到此枚举的变量值将决定程序如何解释某些操作,如鼠标点击等。我想要一个标签(可能在左下角的状态区域)来反映当前 "mode" 应用程序所在的位置,并显示一条可读消息供用户查看。

这是我的枚举:

enum Mode {
    defaultMode,     // Example states that will determine
    alternativeMode; // how the program interprets mouse clicks

    // My attempt at making a property that a label could bind to
    private SimpleStringProperty property = new SimpleStringProperty(this, "myEnumProp", "Initial Text");
    public SimpleStringProperty getProperty() {return property;}

    // Override of the toString() method to display prettier text
    @Override
    public String toString()
    {
        switch(this) {
            case defaultMode:
                return "Default mode";
            default:
                return "Alternative mode";
        }
    }
}

根据我收集到的信息,我正在寻找一种将枚举的 toString() 属性(我将其覆盖为更易于理解的形式)绑定到此标签的方法。绑定是这样的,每当我设置类似

的东西时
applicationState = Mode.alternativeMode;

标签会自动显示 toString() 结果,我不需要每次都放置 leftStatus.setText(applicationState.toString())

这是我尝试过的:(在我的主控制器中 class):

leftStatus.textProperty().bind(applicationState.getProperty());

将标签设置为初始文本,但在我更新 applicationState 枚举时不会更新。

我做错了什么?

使用 asString 从包含 属性 的值的 Property<Mode> 获取 StringBinding 使用对象的 [=17= 转换为 String ]方法。

示例:

@Override
public void start(Stage primaryStage) {
    ComboBox<Mode> combo = new ComboBox<>();
    combo.getItems().setAll(Mode.values());
    Label label = new Label();

    // use "state" property from combo box
    // (you could replace combo.valueProperty() with your own property)
    label.textProperty().bind(combo.valueProperty().asString());

    Scene scene = new Scene(new VBox(combo, label), 200, 200);

    primaryStage.setScene(scene);
    primaryStage.show();
}

否则,如果您想要 属性 值包含在枚举中,您可以使用 Bindings.selectString,前提是您将 getProperty() 方法重命名为 propertyProperty() 以遵守命名约定:

enum Mode {
    ...

    public StringProperty propertyProperty() {return property;}
    ...
}
private final Random random = new Random();

@Override
public void start(Stage primaryStage) {
    ComboBox<Mode> combo = new ComboBox<>();
    combo.getItems().setAll(Mode.values());
    Label label = new Label();

    // use "state" property from combo box
    // (you could replace combo.valueProperty() with your own property)
    label.textProperty().bind(Bindings.selectString(combo.valueProperty(), "property"));

    Scene scene = new Scene(new VBox(combo, label), 200, 200);
    scene.setOnMouseClicked(evt -> {
        // change property values at random
        Mode.defaultMode.propertyProperty().set(random.nextBoolean() ? "a" : "b");
        Mode.alternativeMode.propertyProperty().set(random.nextBoolean() ? "c" : "d");
    });

    primaryStage.setScene(scene);
    primaryStage.show();
}

与其将 属性 添加到枚举 class,不如使用 ObjectProperty for the application state? Have a look at this MCVE:

import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;

public class Example extends Application {

    private ObjectProperty<Mode> appState = new SimpleObjectProperty<>(Mode.DEFAULT);

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        Button btn = new Button("Toggle mode");
        btn.setOnMouseClicked((event) -> appState.setValue(appState.get() == Mode.DEFAULT ? Mode.ALTERNATIVE : Mode.DEFAULT));

        Label lbl = new Label();
        lbl.textProperty().bind(appState.asString());

        FlowPane pane = new FlowPane();
        pane.getChildren().addAll(btn, lbl);

        primaryStage.setScene(new Scene(pane));
        primaryStage.show();
    }

    public enum Mode {
        DEFAULT("Default mode"),
        ALTERNATIVE("Alternative mode");

        private String description;

        private Mode(String description) {
            this.description = description;
        }

        @Override
        public String toString() {
            return description;
        }
    }

}