2014-05-21 16 views
9

Tôi sử dụng JavaFX NumberBindings để tính các giá trị nhất định. Ban đầu mọi thứ hoạt động như mong đợi. Tuy nhiên, sau một khoảng thời gian khá nhỏ, sự ràng buộc chỉ dừng lại khi hoạt động. Tôi cũng không nhận được Ngoại lệ.Ràng buộc Đậu JavaFX đột ngột ngừng hoạt động

Tôi đã thử một số liên kết, cũng như các phương pháp tiếp cận cấp cao và cấp thấp. Ngay cả việc tính toán chính nó (khi bị ghi đè) chỉ dừng lại và không được gọi nữa. Tôi cũng đã cập nhật lên JDK mới nhất (1.8.0_05) và xây dựng lại/khởi động lại mọi thứ.

Ví dụ làm việc tối thiểu sau đây minh họa sự cố. Nó nên System.out.println chiều rộng hiện tại của cửa sổ chính để STDOUT. Sau khi thay đổi kích thước cửa sổ khoảng 10 giây, đầu ra sẽ dừng lại. Tôi cũng đã cố gắng liên kết thuộc tính kết quả với điều khiển JavaFX, để đảm bảo việc sử dụng liên tục của Property, nhưng điều đó không có ích gì. Tôi tin rằng tôi đang thiếu một số hành vi rất cơ bản của tài sản/Bindings ở đây, Google dường như không biết rằng hành vi ở tất cả.

import javafx.application.Application; 
import javafx.beans.binding.NumberBinding; 
import javafx.beans.property.IntegerProperty; 
import javafx.beans.property.SimpleIntegerProperty; 
import javafx.beans.value.ChangeListener; 
import javafx.beans.value.ObservableValue; 
import javafx.scene.Scene; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 

public class BindingsProblem extends Application { 

@Override 
public void start(Stage primaryStage) { 
    // Initialization... 
    StackPane root = new StackPane(); 
    Scene scene = new Scene(root, 300, 250); 
    primaryStage.setScene(scene); 
    primaryStage.show(); 


    // Binding - The problem occurrs here! 
    NumberBinding currentWidthPlusTen = primaryStage.widthProperty().add(10); 
    IntegerProperty boundNumberProperty = new SimpleIntegerProperty(); 
    boundNumberProperty.bind(currentWidthPlusTen); 
    boundNumberProperty.addListener(new ChangeListener<Number>() { 

     @Override 
     public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) { 
      System.out.println(newValue.toString()); 
     } 

    }); 
} 


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

} 
+0

Tôi có thể tạo lại sự cố. Nó trông giống như một con bọ. Bạn đã tìm kiếm trên jira chưa? – assylias

+0

Tôi dường như không thể tìm thấy các báo cáo lỗi hiện có. Nó có vẻ là một cái gì đó rất cơ bản, thật khó để tưởng tượng nó là một lỗi trong bản thân JDK/JRE. – underkuerbis

Trả lời

13

Giá trị sử dụng WeakListener để quan sát giá trị currentWidthPlusTen. Vì bạn không giữ một tham chiếu đến boundNumberProperty, nó đủ điều kiện để thu thập rác ngay sau khi thoát khỏi phương thức start(...). Khi bộ thu gom rác khởi động, tham chiếu bị mất hoàn toàn và ràng buộc không còn hoạt động nữa.

Để thấy điều này trực tiếp, thêm dòng

root.setOnMousePressed(event -> System.gc()); 

với phương pháp start(...). Bạn có thể buộc người nghe phải "ngừng làm việc" bằng cách nhấp vào cửa sổ.

Rõ ràng, đó không phải là những gì bạn muốn: sửa chữa là giữ lại tham chiếu đến boundNumberProperty sau khi thoát start(...). Ví dụ:

import javafx.application.Application; 
import javafx.beans.binding.NumberBinding; 
import javafx.beans.property.IntegerProperty; 
import javafx.beans.property.SimpleIntegerProperty; 
import javafx.beans.value.ChangeListener; 
import javafx.beans.value.ObservableValue; 
import javafx.scene.Scene; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 

public class BindingsProblem extends Application { 

    IntegerProperty boundNumberProperty; 

    @Override 
    public void start(Stage primaryStage) { 
     // Initialization... 
     StackPane root = new StackPane(); 
     Scene scene = new Scene(root, 300, 250); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 

     // Binding - The problem occurrs here! 
     NumberBinding currentWidthPlusTen = primaryStage.widthProperty() 
       .add(10); 

     boundNumberProperty = new SimpleIntegerProperty(); 
     boundNumberProperty.bind(currentWidthPlusTen); 
     boundNumberProperty.addListener(new ChangeListener<Number>() { 

      @Override 
      public void changed(ObservableValue<? extends Number> observable, 
        Number oldValue, Number newValue) { 
       System.out.println(newValue.toString()); 
      } 

     }); 

    } 

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

} 

Cập nhật

Bất cứ ai chạy vào vấn đề này cũng có thể muốn nhìn vào Tomas Mikula của ReactFX, cung cấp một workaround sạch hơn cho điều này (tại các chi phí của việc sử dụng một thư viện của bên thứ ba , mà bạn sẽ cần phải dành thời gian học tập). Tomas giải thích vấn đề này và cách ReactFX giải quyết nó trong this blogsubsequent post.

+5

+1 Wow cũng phát hiện! – assylias

+0

Rất tốt! Điều này giải quyết được vấn đề của tôi. Tôi có xu hướng tin tưởng và dựa vào quản lý bộ nhớ/tham chiếu tự động trong Java. Rõ ràng quá nhiều: D – underkuerbis

+0

Điều thú vị là, hầu hết các lần bạn thực sự sử dụng điều này cho bất kỳ điều gì thực, ngoài các loại kiểm tra đơn giản trong mã mẫu của bạn, vấn đề sẽ biến mất. Ví dụ, nếu bạn tạo một nhãn và gắn kết văn bản của nó với 'IntegerProperty' của bạn, thì dĩ nhiên nhãn hiệu quả giữ một tham chiếu đến thuộc tính, do đó nó không thu thập rác. Đôi khi vấn đề này xuất hiện trong một kịch bản thực tế, nhưng nó rất hiếm. –

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