繁体   English   中英

如何在javaFX中更改StringProperty类型的最终值?

[英]how to change final value of StringProperty type in javaFX?

我试图学习Tableview并得到了一些例子。

我不知道StringProperty如何工作。

尽管Class Person的字段是最终实例,

setEmailButton可以更改其值。

    import javafx.application.Application;
    import javafx.beans.property.*;
    import javafx.collections.*;
    import javafx.event.*;
    import javafx.geometry.Insets;
    import javafx.scene.*;
    import javafx.scene.control.*;
    import javafx.scene.control.cell.PropertyValueFactory;
    import javafx.scene.layout.VBox;
    import javafx.scene.text.Font;
    import javafx.stage.Stage;

    public class PropertyBasedTableView extends Application {
      private TableView<Person> table = new TableView<Person>();
      private final ObservableList<Person> data = FXCollections.observableArrayList();
      private void initData() {
        data.setAll(
          new Person("Jacob", "Smith", "jacob.smith@example.com"),
          new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
          new Person("Ethan", "Williams", "ethan.williams@example.com")
        );
      }

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

      @Override public void start(Stage stage) {
        initData();

        stage.setTitle("Table View Sample");
        stage.setWidth(450);
        stage.setHeight(500);

        final Label label = new Label("Address Book");
        label.setFont(new Font("Arial", 20));

        TableColumn firstNameCol = new TableColumn("First Name");
        firstNameCol.setMinWidth(100);
        firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));

        TableColumn lastNameCol = new TableColumn("Last Name");
        lastNameCol.setMinWidth(100);
        lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));

        TableColumn emailCol = new TableColumn("Email");
        emailCol.setMinWidth(200);
        emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email"));

        table.setItems(data);
        table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
        table.setPrefHeight(300);

        final Button setEmailButton = new Button("Set first email in table to wizard@frobozz.com");
        setEmailButton.setOnAction(new EventHandler<ActionEvent>() {
          @Override public void handle(ActionEvent event) {
            if (data.size() > 0) {
              data.get(0).setEmail("wizard@frobozz.com");
            }  
          }
        });


        final VBox vbox = new VBox(10);
        vbox.setPadding(new Insets(10, 0, 0, 10));
        vbox.getChildren().addAll(label, table, setEmailButton);

        stage.setScene(new Scene(new Group(vbox)));
        stage.show();
      }

      public static class Person {
        private final StringProperty firstName;
        private final StringProperty lastName;
        private final StringProperty email;

        private Person(String fName, String lName, String email) {
          this.firstName = new SimpleStringProperty(fName);
          this.lastName = new SimpleStringProperty(lName);
          this.email = new SimpleStringProperty(email);
        }

        public String getFirstName() { return firstName.get(); }
        public void setFirstName(String fName) { firstName.set(fName); }
        public StringProperty firstNameProperty() { return firstName; }
        public String getLastName() { return lastName.get(); }
        public void setLastName(String lName) { lastName.set(lName); }
        public StringProperty lastNameProperty() { return lastName; }
        public String getEmail() { return email.get(); }
        public void setEmail(String inMail) { email.set(inMail); }
        public StringProperty emailProperty() { return email; }  // if this method is commented out then the tableview will not refresh when the email is set.
      }
    }

然后我自己下结论:“尤里卡!最终StringProperty类型的值可以更改!”

所以我做了测试

    package zzzzDelete;

    import javafx.application.Application;
    import javafx.beans.property.SimpleStringProperty;
    import javafx.beans.property.StringProperty;
    import javafx.stage.Stage;

    class A{

        void someTest(){
            B insB = new B("why");
            System.out.println(insB.getString());
            insB.setString("omg");
            System.out.println(insB.getString());
        }

        class B{
            private final StringProperty someString;
            private B(String someString){
                this.someString = new SimpleStringProperty(someString);
            }

            public String getString(){
                return someString.get();
            }

            public void setString(String newString){
                this.someString = new SimpleStringProperty(newString);      // error
            }

        }
    }

    public class SomeTest {
        public static void main(String[] args){
            A a = new A();
            a.someTest();
        }
    }

由于final关键字而发生错误。

我对第一个例子和第二个例子非常困惑。

初始化后,您不能更改不可变( final )字段(在构造函数中发生)。 相反,只需通过setValue(String)设置StringProperty的值:

class B {
    private final StringProperty someString;

    private B(String someString){
        this.someString = new SimpleStringProperty(someString);
    }

    public String getString(){
        return someString.get();
    }

    public void setString(String newString){
        this.someString.setValue(newString);
    }

    public StringProperty stringProperty() {
        return this.someString;
    }
}

阅读JavaFX:属性和绑定教程 ,了解如何使用JavaFX属性。

下图应阐明更改StringProperty工作方式:

引用someString(红色)是最终的,不能更改

类型B对象始终引用相同的StringProperty对象,因为引用someStringfinal并且不能更改(请参见红色箭头)。 但是someString引用的SimpleStringProperty对象是可变的 它包含一个名为valueString引用(请参见绿色箭头),可以将其更改为指向另一个String对象,例如,通过调用setValue("second") (请参见绿色的虚线箭头)。

将变量标记为final ,只能为其分配一个值。 在第二个示例中,由于尝试在setString(...)方法中为someString分配值,因此会出现编译错误:

this.someString = new SimpleStringProperty(newString);

不允许这样做,因为setString(...)方法可以在同一对象上多次调用。

相比之下,在您的第一个示例中,只有final变量(实例字段)才被赋值,这是在构造函数中进行的,当然,对于任何给定的对象只能调用一次。

注意, 给引用赋值是有区别的:

this.someString = new SimpleStringProperty(...);

更改参考指向的对象的状态

this.firstName.set(fName);

即使firstNamefinal ,第二个也很好。

如果您在第二个示例中编写类B以遵循与第一个示例中的Person类相同的模式,则它将正常工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM