JavaFX-水平选框文本

JavaFX-水平选框文本,java,javafx,javafx-2,marquee,Java,Javafx,Javafx 2,Marquee,我试图达到类似于在水平轴上移动的长文本行的效果。我设法使它工作,但我不能说它令人满意 我的控制器类如下所示: @FXML private Text newsFeedText; (...) @Override public void initialize(URL url, ResourceBundle resourceBundle) { TranslateTransition transition = TranslateTransitionBuilder.create()

我试图达到类似于在水平轴上移动的长文本行的效果。我设法使它工作,但我不能说它令人满意

我的
控制器
类如下所示:

@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();
}
newsFeedText
绑定到某个动态更新的文本源,因此它包含不同数量的文本

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

  • -width
    过渡到
    +width
    <代码>宽度是监视器的分辨率宽度
若窗口并没有完全屏蔽,那个么会有文本根本看不见的时刻。 如果文本变长,且
newsFeedText
width将大于监视器的分辨率宽度,则过渡将“一分为二”消失(仍在屏幕上)

  • 当前,
    持续时间
    不依赖于
    新闻提要文本
    的宽度
现在,这没什么大不了的,但是如果动态计算过渡的
fromX
toX
,那么它将产生不同的选框速度


如何消除这些缺点?

您应该能够通过收听场景的
widthProperty
来做到这一点。您可以通过
newsFeedText.getScene().widthProperty()
访问它,或者从主类中获取一个引用并从那里公开它,或者将它传递给一个方法或构造函数,以便在声明
newsFeedText
的类中进行访问

这种方法的好处是,现在您的逻辑取决于场景的宽度(动态依赖项),而不是监视器的宽度(静态依赖项)。请注意,我还没有测试过这种方法,但目前看不出它不起作用的原因(可能是天真的)

至于持续时间依赖关系,可以根据
newsFeedText
中的文本长度执行某种计算来解决。类似于
Duration.seconds(newsFeedText.get Text().length()/deminator)
的内容,其中
deminator
是您指定的某个值(例如7500,如代码中的值)。这将根据文本的长度动态计算持续时间


如果要使用
newsFeedText
本身的宽度而不是文本的长度进行操作,只需将
newsFeedText.getText().length()
替换为
newsFeedText.getWidth()
。确保在布局了
newsFeedText
之后执行此计算,以便调用获取其宽度返回实际宽度。您还可以使用
getPrefWidth()
getMinWidth()
getMaxWidth()
中的任何一个替换调用。我已设法使其工作,任何重新计算只能在转换停止后进行,因此我们无法将其
循环计数设置为
时间线。不确定的
。我的要求是我可以更改组件内的文本,以便有fxml连接:

@FXML
private Text node; // text to marquee

@FXML
private Pane parentPane; // pane on which text is placed
有效的守则是:

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();
重新计算Transition()
是:

private void rerunAnimation() {
    transition.stop();
    // if needed set different text on "node"
    recalculateTransition();
    transition.playFromStart();
}
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));
}

这是另一个问题出现的地方,如果绑定
TranslateTransition#toX
,调用
TranslateTransition#play
并更改窗口大小,则在停止并再次播放之前,transition不会更改其
toX
。在我的例子中,代码是在
Initializable#initialize
方法中调用的,因此此时我的场景的大小等于零。请使用在width属性上注册的
ChangeListener
。在那里,将您的转换值设置为<代码> ChangeListener 所报告的新值。考虑将MouQee控件捐赠给它。它在所有窗口宽度内工作,但如果我需要内部控件,怎么办?我无法隐藏文本particulary@jewelsea我认为我的“解决方案”效率太低,但在空闲的时候,我一定会改进它并捐赠解决方案。也考虑在矩形框文本下放置一个矩形形状,其大小大于可见屏幕区域,以实现平滑动画。文本形状必须在该矩形的所有路径上运行。不要忘记设置形状的缓存。