javaFX中是否存在等价的枚举属性类型?

rvi*_*t34 8 java javafx javafx-8

我想观察一些java bean类的某些字段所做的更改.
该字段是枚举类型.
要绑定字段和相应的ui控件我将PropertyChangeListener按照此处所述使用
但似乎javaFX没有等效的枚举属性类型.像javafx.beans.property.EnumProperty
我试图使用的东西StringProperty,ObjectProperty但它不起作用.

更新:添加了sscce

Observable.java

package sample;

    import java.beans.PropertyChangeListener;
    import java.beans.PropertyChangeSupport;

    public class Observable {

        protected PropertyChangeSupport propertyChangeSupport = null;

        public Observable() {}

        public void setObservableObject (Observable observable) {
            propertyChangeSupport = new PropertyChangeSupport(observable);
        }

        public void addPropertyChangeListener(PropertyChangeListener listener){
            System.out.println("added PropertyChangeListener");
            propertyChangeSupport.addPropertyChangeListener(listener);
        }
    }
Run Code Online (Sandbox Code Playgroud)

Item.java

package sample;


    public class Item extends Observable {

        public enum State {
            INIT, STARTED
        }

        private String name;
        private State state = State.INIT;

        public Item() {
            super();
            super.setObservableObject(this);
        }

        public Item(String name, State state) {
            this();
            setName(name);
            setState(state);
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public State getState() {
            return state;
        }

        public void setState(State state) {
            State oldState = this.state;
            this.state = state;
            System.out.println(String.format("%s: change state from %s to %s",name,oldState.name(),state));
            propertyChangeSupport.firePropertyChange("state", oldState, state);
        }


    }
Run Code Online (Sandbox Code Playgroud)

Main.java

package sample;

    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;

    public class Main extends Application {

        @Override
        public void start(Stage primaryStage) throws Exception {
            Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
            primaryStage.setTitle("Item View");
            primaryStage.setScene(new Scene(root, 200, 100));
            primaryStage.show();
        }


        public static void main(String[] args) {
            launch(args);
        }
    }
Run Code Online (Sandbox Code Playgroud)

sample.fxml

<?xml version="1.0" encoding="UTF-8"?>

    <?import javafx.scene.control.Button?>
    <?import javafx.scene.control.CheckBox?>
    <?import javafx.scene.control.ComboBox?>
    <?import javafx.scene.control.Label?>
    <?import javafx.scene.layout.AnchorPane?>

    <AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="108.0" prefWidth="225.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
             <children>
                <Label layoutX="14.0" layoutY="14.0" text="show item" />
                <ComboBox fx:id="cbxItemsSelector" layoutX="14.0" layoutY="31.0" prefWidth="150.0" />
                <Button fx:id="btnChangeState" layoutX="14.0" layoutY="65.0" mnemonicParsing="false" onAction="#changeItemState" prefHeight="25.0" prefWidth="85.0" text="change state" />
             </children>
    </AnchorPane>
Run Code Online (Sandbox Code Playgroud)

Controller.java

package sample;

    import javafx.beans.Observable;
    import javafx.beans.property.adapter.JavaBeanObjectPropertyBuilder;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.fxml.FXML;
    import javafx.scene.control.ComboBox;
    import javafx.scene.control.ListCell;
    import javafx.scene.control.ListView;
    import javafx.util.Callback;


    import java.util.ArrayList;
    import java.util.List;

    public class Controller {

        @FXML
        private ComboBox<Item> cbxItemsSelector;

        private ObservableList<Item> items;

        public void initialize() {
            loadItems();
            customizeSelectorCellView();
        }

        private void loadItems() {
            List<Item> itemsList = new ArrayList<>();
            itemsList.add(new Item("first item", Item.State.INIT));
            itemsList.add(new Item("second item", Item.State.INIT));

            items = FXCollections.observableList(itemsList, item -> {
                try {
                    return new Observable[]{
                            new JavaBeanObjectPropertyBuilder().bean(item).name("state").build()
                    };
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                    return new Observable[]{};
                }
            });

            cbxItemsSelector.setItems(items);
        }

        private void customizeSelectorCellView() {


            cbxItemsSelector.setButtonCell(new ListCell<Item>() {
                @Override
                protected void updateItem(Item item, boolean empty) {
                    super.updateItem(item, empty);
                    if (empty) {
                        setText("");
                    } else {
                        setText(item.getName());
                    }
                }
            });
            cbxItemsSelector.setCellFactory(
                    new Callback<ListView<Item>, ListCell<Item>>() {
                        @Override
                        public ListCell<Item> call(ListView<Item> p) {
                            ListCell cell = new ListCell<Item>() {
                                @Override
                                protected void updateItem(Item item, boolean empty) {
                                    super.updateItem(item, empty);
                                    if (empty) {
                                        setText("");
                                    } else {
                                        System.out.println(String.format("update %s",item.getName()));
                                        setText(String.format("name: %s\n state: %s\n", item.getName(), item.getState().name()));
                                    }
                                }
                            };
                            return cell;
                        }
                    }
            );
        }

        @FXML
        public void changeItemState() {
            Item selectedItem = cbxItemsSelector.getSelectionModel().getSelectedItem();
            if (selectedItem == null) return;

            selectedItem.setState(Item.State.STARTED);

        }

    }
Run Code Online (Sandbox Code Playgroud)

所以,当我现在运行它时,我将获得下一个输出:

first item: change state from INIT to INIT
second item: change state from INIT to INIT
added PropertyChangeListener
added PropertyChangeListener
update first item
update second item
update first item
update second item
update first item
update first item
update second item
first item: change state from INIT to STARTED
second item: change state from INIT to STARTED
Process finished with exit code 0
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,在更改项目状态后未调用更新项目.
我使用:jdk中包含的jre 1.8.0_91-b15 x64

小智 0

@rvit34 - 要么重命名sample.Observable(我重命名为MyObservable),显式地import sample.Observable;在 中sample.Item,要么更改行:

public class Item extends Observable {
Run Code Online (Sandbox Code Playgroud)

到:

public class Item extends sample.Observable {
Run Code Online (Sandbox Code Playgroud)

它应该可以解决你的问题。以下是:

1) 修改后的示例代码产生的输出

2)对原始源文件所做的所有更改(为简洁起见,我仅包含更改而不是整个示例代码)

3) 解释导致问题的原因以及避免未来出现类似性质问题的技术。

我的输出:

run:
first item: change state from INIT to INIT...
...
first item: change state from INIT to STARTED
update first item
second item: change state from INIT to STARTED
update second item
first item: change state from STARTED to INIT
update first item
second item: change state from STARTED to INIT
update second item
BUILD SUCCESSFUL (total time: 32 seconds)
Run Code Online (Sandbox Code Playgroud)

MyObservable.java(从 Observable.java 重命名)

public class MyObservable {
...
}
Run Code Online (Sandbox Code Playgroud)

项目.java

public class Item extends MyObservable {
    ...
    public MyObservable() {}

    public void setObservableObject (MyObservable observable) {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

Controller.java(不需要使其工作。修改为循环状态,而不是仅仅设置为 STARTED)

public void changeItemState() {
        Item selectedItem = cbxItemsSelector.getSelectionModel().getSelectedItem();
        if (selectedItem != null) {

            switch (selectedItem.getState()) {
                case STARTED:
                    selectedItem.setState(Item.State.INIT);
                    break;
                case INIT:
                    selectedItem.setState(Item.State.STARTED);
                    break;
                default:
                    break;
            }
        }

    }
Run Code Online (Sandbox Code Playgroud)

问题(以及发生正确行为的机会)来自名称空间冲突。

sample.Item下降自sample.Observable. 因为这两个类都是 package 的成员sample,所以您既不必导入也不必在声明时sample.Observable显式声明您的意思,这通常不会成为问题。因为,您使用in ,它似乎会混淆 JRE(实际上不应该如此,这可能是您正在发现的 JVM 中的错误)。随机成功运行可能是由于系统负载或其他一些随机环境变量或条件导致 jvm 挂起加载 javafx.beans.Observable 直到将 Item 注册为类型为 Sample.Observable 的对象之后,或者 Sample.Observable 已经启动时已加载到内存中。sample.ObservableItem extends Observablejavafx.beans.ObservableMain

编辑 - 上面的内容实际上并没有回答帖子标题中提出的问题,但它确实解决了帖子正文中讨论的问题。为了回答标题问题, aSetProperty<E>看起来非常适合用作枚举属性。还没有尝试在提供的示例代码中实现这一点,可能不会,但我将使用我当前正在处理的项目中的一个工作示例重新编辑,这让我寻找标题问题的答案。