2014-05-07 20 views
16

Tôi muốn sử dụng các thuộc tính JavaFX cho ràng buộc giao diện người dùng, nhưng tôi không muốn chúng trong các lớp mô hình của tôi (xem Using javafx.beans properties in model classes). Các lớp mô hình của tôi có getters và setters, và tôi muốn tạo các thuộc tính dựa trên chúng. Ví dụ, giả sử một thể hiện bean với các phương pháp String getName()setName(String name), tôi sẽ viếtGói JavaBean với các thuộc tính JavaFX

SimpleStringProperty property = new SimpleStringProperty(bean, "name") 

mong rằng property.set("Foobar") sẽ châm ngòi cho một cuộc gọi đến bean.setName. Nhưng điều này dường như không hoạt động. Tôi đang thiếu gì?

+0

Không loại bỏ hoàn toàn ý tưởng sử dụng thuộc tính javafx trong các lớp mô hình của bạn. Tôi đã thêm một câu trả lời thay thế cho câu hỏi mà bạn đã liên kết: đó có thể là một cách tiếp cận đáng để suy nghĩ. –

Trả lời

36

Lớp học Simple*Property đầy đủ, triển khai độc lập các lớp trừu tượng tương ứng Property và không dựa vào bất kỳ đối tượng nào khác. Vì vậy, ví dụ: SimpleStringProperty chứa trường (riêng) String giữ giá trị hiện tại của thuộc tính.

Các thông số cho constructor bạn cho thấy:

new SimpleStringProperty(bean, "name") 

là:

  • bean: đậu mà tài sản thuộc, nếu có
  • name: tên của thuộc tính

bean có thể hữu ích trong phương thức changed(...) của ChangeListener vì bạn có thể truy xuất "bean sở hữu" của thuộc tính đã thay đổi từ chính thuộc tính. name có thể được sử dụng tương tự (nếu bạn có cùng một trình nghe được đăng ký với nhiều thuộc tính, bạn có thể tìm ra thuộc tính nào đã thay đổi: mặc dù tôi không bao giờ sử dụng mẫu này).

Vì vậy, việc sử dụng điển hình của một SimpleStringProperty như một tài sản quan sát được của một đối tượng trông giống như:

public class Person { 
    private final StringProperty firstName 
     = new SimpleStringProperty(this, "firstName"); 

    public final String getFirstName() { 
     return firstName.get(); 
    } 

    public final void setFirstName(String firstName) { 
     this.firstName.set(firstName); 
    } 

    public StringProperty firstNameProperty() { 
     return firstName ; 
    } 

    // ... other properties, etc 
} 

Các chức năng bạn đang tìm kiếm: để quấn một tài sản kiểu Java Bean hiện có trong một tài sản quan sát JavaFX được thực hiện theo các lớp học trong gói javafx.beans.property.adapter. Vì vậy, ví dụ, bạn có thể làm

StringProperty nameProperty = new JavaBeanStringPropertyBuilder() 
     .bean(bean) 
     .name("name") 
     .build(); 

Calling

nameProperty.set("James"); 

với thiết lập này một cách hiệu quả sẽ gây ra một cuộc gọi đến

bean.setName("James"); 

Nếu đậu hỗ trợ PropertyChangeListener s, JavaBeanStringProperty sẽ đăng ký a PropertyChangeListener với đậu. Bất kỳ thay đổi nào đối với thuộc tính name của Java Bean sẽ được dịch bởi số JavaBeanStringProperty thành các thay đổi thuộc tính JavaFX. Do đó, nếu các JavaBean cơ bản hỗ trợ PropertyChangeListener s, sau đó thay đổi đến bean qua

bean.setName(...); 

sẽ dẫn đến bất kỳ ChangeListener s (hoặc InvalidationListener s) đăng ký với JavaBeanStringProperty được thông báo về sự thay đổi.

Vì vậy, ví dụ, nếu lớp Bean là

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

public class Bean { 

    private String name ; 
    private final PropertyChangeSupport propertySupport ; 

    public Bean(String name) { 
     this.name = name ; 
     this.propertySupport = new PropertyChangeSupport(this); 
    } 

    public Bean() { 
     this(""); 
    } 

    public String getName() { 
     return name ; 
    } 

    public String setName(String name) { 
     String oldName = this.name ; 
     this.name = name ; 
     propertySupport.firePropertyChange("name", oldName, name); 
    } 

    public void addPropertyChangeListener(PropertyChangeListener listener) { 
     propertySupport.addPropertyChangeListener(listener); 
    } 
} 

Sau đó, đoạn mã sau:

Bean bean = new Bean(); 
StringProperty nameProperty() = new JavaBeanStringPropertyBuilder() 
     .bean(bean) 
     .name("name") 
     .build(); 
nameProperty().addListener((obs, oldName, newName) -> System.out.println("name changed from "+oldName+" to "+newName)); 
bean.setName("James"); 
System.out.println(nameProperty().get()); 

sẽ cho kết quả:

name changed from to James 
James 

Nếu JavaBean không hỗ trợ PropertyChangeListener s, sau đó thay đổi đối với bean qua bean.setName(...) sẽ không lan truyền đến ChangeListener s hoặc InvalidationListener s đã đăng ký với số JavaBeanStringProperty.

Vì vậy, nếu chỉ đơn giản là đậu

public class Bean { 

    public Bean() { 
     this(""); 
    } 

    public Bean(String name) { 
     this.name = name ; 
    } 

    private String name ; 

    public String getName() { 
     return name ; 
    } 

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

là The JavaBeanStringProperty sẽ không có cách nào để quan sát sự thay đổi, vì vậy người nghe thay đổi sẽ không bao giờ được gọi bằng một cuộc gọi đến bean.setName(). Vì vậy, mã kiểm tra ở trên chỉ đơn giản là sẽ xuất ra

James 
+0

+1 giải thích tốt. JavaBeanStringPropertyBuilder sẽ thêm hỗ trợ PropertyChangeListener cho bean. Từ câu trả lời nó âm thanh với tôi như người dùng nên thêm hỗ trợ mình cho đậu. –

+0

Không hoàn toàn: 'JavaBeanStringProperty' không thêm hỗ trợ' PropertyChangeListener' vào bean. Đã cập nhật câu trả lời để làm rõ. –

+0

Bạn có phiền không nếu tôi yêu cầu bạn cũng hiển thị một mẫu Java Bean có và không có sự hỗ trợ của PropertyChangeListener? –

Các vấn đề liên quan