JavaFX - 水平选框文本

Mac*_*ski 5 java javafx marquee javafx-2

我试图实现类似于marquee的效果- 在水平轴上移动的长(在我的情况下)文本的行.我设法让它工作,但我不能称之为令人满意.

我的Controller课程如下:

@FXML
private Text newsFeedText;

(...)
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
    TranslateTransition transition = TranslateTransitionBuilder.create()
            .duration(new Duration(7500))
            .node(newsFeedText)
            .interpolator(Interpolator.LINEAR)
            .cycleCount(Timeline.INDEFINITE)
            .build();   

    GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
    int width = gd.getDisplayMode().getWidth();

    transition.setFromX(width);
    transition.setToX(-width);
    transition.play();
}
Run Code Online (Sandbox Code Playgroud)

newsFeedText 绑定到一些动态更新的文本源,因此它包含不同数量的文本.

我的代码至少有两个缺点:

  • 转变从去-width+width; width是显示器的分辨率宽度

如果窗口没有经过全面筛选,有时会看不到文本.如果文本更长并且newsFeedText宽度将大于显示器的分辨率宽度,则转换将"消失"(仍然在屏幕上).

  • 目前Duration不依赖于宽度newsFeedText.

现在,它没有任何意义,但如果过渡fromXtoX动态计算,那么它将导致各种速度的选框.

如何摆脱这些弊端?

Mac*_*ski 5

我已经设法使它工作,只有在转换停止后才能进行任何重新计算,因此我们无法将其设置cycleCountTimeline.INDEFINITE.我的要求是我可以更改组件内的文本,因此有fxml接线:

@FXML
private Text node; // text to marquee

@FXML
private Pane parentPane; // pane on which text is placed
Run Code Online (Sandbox Code Playgroud)

有效的代码是:

transition = TranslateTransitionBuilder.create()
        .duration(new Duration(10))
        .node(node)
        .interpolator(Interpolator.LINEAR)
        .cycleCount(1)
        .build();

transition.setOnFinished(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent actionEvent) {
        rerunAnimation();
    }
});

rerunAnimation();
Run Code Online (Sandbox Code Playgroud)

在哪里rerunAnimation():

private void rerunAnimation() {
    transition.stop();
    // if needed set different text on "node"
    recalculateTransition();
    transition.playFromStart();
}
Run Code Online (Sandbox Code Playgroud)

recalculateTransition()是:

private void recalculateTransition() {
    transition.setToX(node.getBoundsInLocal().getMaxX() * -1 - 100);
    transition.setFromX(parentPane.widthProperty().get() + 100);

    double distance = parentPane.widthProperty().get() + 2 * node.getBoundsInLocal().getMaxX();
    transition.setDuration(new Duration(distance / SPEED_FACTOR));
}
Run Code Online (Sandbox Code Playgroud)