使用自定义asString方法将simpleStringProperty绑定到simpleIntegerProperty

时间:2019-01-31 04:25:59

标签: javafx binding

我有一个simpleIntegerProperty,表示要以hh:mm:ss格式表示的数量(以秒为单位)。

我想通过将Label textProperty绑定到simpleIntegerProperty在Label中呈现此内容。我知道我可以使用格式字符串执行类似的操作,例如

activeTimeText.textProperty().bind(model.activeTimeSeconds.asString("Seconds: %04d"));

渲染:

Seconds: 0000

那么问题是,如何实现更复杂的asString转换?例如,我当前所需的输出输出(其中的数字是秒钟simpleIntegerProperty的函数。):

00:00:00

我已经搜索了类似的问题,因为我认为这很普遍。但是还没有找到答案。抱歉,如果这是重复的话。

2 个答案:

答案 0 :(得分:2)

您可以扩展SimpleIntegerProperty以覆盖asString

class MySimpleIntegerProperty extends SimpleIntegerProperty{

    @Override
    public StringBinding asString(){
         return Bindings.createStringBinding(() -> " hello " + get() ,    this);
    }
}

要测试使用:

MySimpleIntegerProperty activeTimeSeconds = new MySimpleIntegerProperty();
activeTimeSeconds.set(7);

SimpleStringProperty activeTimeText = new SimpleStringProperty();
activeTimeText.bind(activeTimeSeconds.asString());
System.out.println(activeTimeText.get());

您当然可以将值处理委托给方法:

@Override
public StringBinding asString(){
    return Bindings.createStringBinding(() -> processValue(get()), this);
}

private String processValue(int value){     
    return " hello " + get() ;
}

答案 1 :(得分:1)

NumberExpression.asString(String)按照Formatter的规则格式化数字,就像使用String.formatPrint[Stream|Writer].printf一样。不幸的是,除非我缺少某些内容,否则Formatter类期望日期/时间对象表示时间上的 moment ,而不是时间上的 duration 。要使用HH:MM:SS格式将属性设置为持续时间,则需要创建自己的绑定。

要获得String,您仍然可以使用String.format,但要格式化为整数而不是时间。这需要您计算小时,分钟和秒。

String str = String.format("%02d:%02d:%02d", hours, minutes, seconds);

如果您使用的是Java 9+,则java.time.Duration可以非常容易地计算小时,分钟和秒。该类在Java 9中添加了toHoursParttoMinutesParttoSecondsPart和其他类似方法。如果使用Java 8,则需要手动进行计算或引入库,有关这方面的帮助,请参见this question

下面是一个示例,假设使用Java 9+,并使用Bindings.createStringBinding创建绑定:

import java.time.Duration;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Main extends Application {

  private final IntegerProperty seconds = new SimpleIntegerProperty(this, "seconds");

  @Override
  public void start(Stage primaryStage) {
    Label label = new Label();
    label.textProperty().bind(Bindings.createStringBinding(() -> {
      // java.time.Duration
      Duration duration = Duration.ofSeconds(seconds.get());
      return String.format("%02d:%02d:%02d", duration.toHoursPart(),
          duration.toMinutesPart(), duration.toSecondsPart());
    }, seconds));

    primaryStage.setScene(new Scene(new StackPane(label), 500, 300));
    primaryStage.show();

    Timeline timeline = new Timeline(
        new KeyFrame(javafx.util.Duration.seconds(1.0), e -> seconds.set(seconds.get() + 1))
    );
    timeline.setCycleCount(Animation.INDEFINITE);
    timeline.play();
  }

}