【问题标题】:Binding an enum's toString() to a Label将枚举的 toString() 绑定到标签
【发布时间】:2016-10-22 00:49:22
【问题描述】:

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

这是我的枚举:

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

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

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

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

我做错了什么?

【问题讨论】:

    标签: javafx binding enums label


    【解决方案1】:

    为什么不使用ObjectProperty 来表示应用程序状态,而不是向枚举类添加属性?看看这个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;
            }
        }
    
    }
    

    【讨论】:

    • 这是一个绝妙的答案,正是我所需要的。对于任何可能偶然发现这一点的未来人,我可能会补充说,我必须调整我的 switch 语句(当我检查我所处的模式时)以在最后添加一个 .get() 。其他一切都完美无缺。谢谢你们的回答,我会选择这个作为最好的,因为它最优雅且易于实现。
    【解决方案2】:

    使用asStringProperty&lt;Mode&gt; 中获取一个StringBinding,其中包含使用对象的toString 方法转换为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();
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-21
    • 2015-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多