2016-10-22 2 views
1

Я установил мое приложение, чтобы изменить его функцию на основе перечисления. Значение переменной, связанной с этим перечислением, определит, как программа интерпретирует определенные действия, такие как щелчки мыши и т. Д. Мне нужен ярлык (возможно, в области статуса внизу слева), чтобы отразить то, что находится в текущем «режиме» приложения, и отобразить читаемое сообщение для пользователя.Связывание указателя enum toString() с меткой

Вот мое перечисление:

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 ENUM.

Что я делаю неправильно?

ответ

2

Вместо добавления свойства в класс перечисления, почему бы не использовать 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; 
     } 
    } 

} 
+0

Это фантастический ответ и именно то, что мне нужно. Для любых будущих людей, которые могут наткнуться на это, я мог бы добавить, что мне пришлось корректировать свои операторы switch (когда я проверил, в каком режиме я был), чтобы добавить в конец .get() в конце. Все остальное работает безупречно. Спасибо вам за ваши ответы, я выберу это как лучшее, потому что это самый элегантный и простой в использовании. – Prester

1

Используйте asString, чтобы получить StringBinding от Property<Mode>, содержащего значения свойства преобразуется в String с помощью метода toString объекта.

Пример:

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

Лично я думаю, что [перечисления должны быть без гражданства] (http://stackoverflow.com/q/540293/3429133) и, следовательно, не должно предлагать связываемое свойство. – beatngu13