有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我想观察一些JavaBean类的某些字段中所做的更改
此字段为枚举类型
要绑定字段和相应的ui控件,我将使用PropertyChangeListener,如所述here
但javaFX似乎没有enum属性类型的等价项。类似于javafx.beans.property.EnumProperty
我试着用StringPropertyObjectProperty代替,但它不起作用

更新添加了一个sscce

可观察到。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);
        }
    }

项目。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);
        }


    }

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

样本。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>

控制器。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);

        }

    }

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

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

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


共 (1) 个答案

  1. # 1 楼答案

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

    public class Item extends Observable {
    

    致:

    public class Item extends sample.Observable {
    

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

    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)
    

    我可以观察到。java(从Observable.java重命名)

    public class MyObservable {
    ...
    }
    

    项目。java

    public class Item extends MyObservable {
        ...
        public MyObservable() {}
    
        public void setObservableObject (MyObservable observable) {
            ...
        }
    }
    

    控制器。java(不需要使其工作。修改为循环状态,而不是仅设置为启动)

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

    问题(以及正常行为的发生概率)来自命名空间冲突

    sample.Itemsample.Observable下降。因为这两个类都是包sample的成员,所以当您声明Item extends Observable时,您既不必导入sample.Observable,也不必显式声明您的意思是sample.Observable,这通常不会是问题。因为,在Main中使用javafx.beans.Observable,这似乎会混淆JRE(它实际上不应该这样做,这可能是您正在发现的JVM中的一个错误)。随机成功运行可能是由于系统负载或其他一些随机环境变量或条件导致jvm挂起加载javafx。豆。直到将项目注册为样本类型的对象后才可见。可观察的,可观察的或样品的。Observable在发射时已经载入内存

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