我正在尝试实现类似于 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();
}
newsFeedText
绑定(bind)到一些动态更新的文本源,因此它包含各种数量的文本。
我的代码至少有两个缺点:
- 过渡从
-width
到+width
;width
是显示器的分辨率宽度
如果窗口未全屏显示,有时文本根本不可见。
如果文本会更长并且 newsFeedText
宽度将大于显示器的分辨率宽度,那么过渡将消失“一半”(仍在屏幕上)。
- 目前
Duration
不依赖于newsFeedText
的宽度。
现在,这没什么了不起的,但是如果转换的 fromX
和 toX
是动态计算的,那么它将导致各种速度的选框。
如何摆脱这些弊端?
最佳答案
我已经让它工作了,任何重新计算只能在转换停止后发生,所以我们不能将它的 cycleCount
设置为 Timeline.INDEFINITE
。我的要求是我可以更改组件内的文本,以便有 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();
rerunAnimation()
是:
private void rerunAnimation() {
transition.stop();
// if needed set different text on "node"
recalculateTransition();
transition.playFromStart();
}
和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));
}
关于JavaFX - 水平字幕文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23062430/