2014-03-25 29 views
0

我使用JavaFX新发布的Java 8版本。JavaFX:GUI未刷新

我写了这个小测试程序来模拟我的问题。

public class Main extends Application{ 

    DoubleProperty widthProperty; 

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

    } 

    @Override 
    public void start(Stage primaryStage){ 
     HBox root = new HBox(); 
     HBox root2 = new HBox(); 
     HBox root3 = new HBox(); 

     Scene scene = new Scene(root, 1200, 800); 

     primaryStage.setScene(scene); 
     primaryStage.show(); 

     widthProperty = new SimpleDoubleProperty(400); 

     root2.setPrefSize(400, 400); 
     root3.setPrefHeight(400); 
     root3.prefWidthProperty().bind(widthProperty); 

     root2.setStyle("-fx-background-color: green"); 
     root3.setStyle("-fx-background-color: red"); 

     root2.setOnMouseClicked(new EventHandler<MouseEvent>() { 
      @Override 
      public void handle(MouseEvent event) { 
       root2.setMinWidth(600); 
      } 
     }); 

     root2.widthProperty().addListener(new ChangeListener<Number>() { 

      @Override 
      public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) { 
      Platform.runLater(new Runnable() { 
       @Override 
       public void run() { 
        widthProperty.set((Double) newValue); 
       } 
      }); 

      //widthProperty.set((Double) newValue); 
     } 
    }); 

    root.getChildren().addAll(root2, root3); 
} 

}

所以会发生什么,如果我的根-2点击,它的宽度改变。 changelistener识别它并将width属性设置为root2的宽度。 width属性绑定到root3的宽度。所以现在root3的宽度也应该改变。

但问题是,我必须在root2上单击两次。只有第二次点击后,GUI才会更新。如果我使用Platform.runlater,GUI会在第一次点击后及时更新。

回答

0

在鼠标单击事件中,您正在更改root2的minWidth,但是您要在root2的widthProperty更改上设置widthProperty变量。 minWidthPropertywidthProperty是两个不同的属性,但widthProperty是只读属性,不能由应用程序设置。它将由布局过程中的父节点(窗口大小调整等)控制,具有关于宽度的最小值,最大值和首选值。因此,请将监听器添加到minWidthProperty中:

root2.minWidthProperty().addListener(new ChangeListener<Number>() { 
    @Override 
    public void changed(ObservableValue<? extends Number> observable, Number oldValue, final Number newValue) { 
     widthProperty.set((Double) newValue); 
    } 
}); 

那么,为什么它使用Platform.runLater?
目前我不能给你一个具体的解释,因为没有深入观察JavaFX的系统架构。但是原因在于FPS机制,应用程序线程和JavaFX的渲染器之间。也就是说,您的widthProperty的值更改事件可能无法在minWidthProperty的同一个“时钟周期”中捕获。

+0

我检查了root2的宽度是否发生了变化。然后我检查了root3的宽度是否也发生了变化,它的确如此,所以bouth hbox的宽度设置正确,但ui没有刷新。 – AKR

+0

@AKR请参阅更新。 –

+0

是的,你是对的,宽度属性是只读的,但在这一点上这是很重要的。最小宽度设置为400到600,因此宽度也会改变。以最小宽度监听器,结果是一样的。 – AKR