I am trying to achieve effect similar to marquee - line of long (in my case) text which is moved in horizontal axis. I managed to get it work, but I can't call it satisfactory.
My Controller
class looks as below:
@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
is binded to some text source which is dynamically updated, so it contains various amount of text.
My code has at least two drawbacks:
-width
to +width
; width
is monitor's resolution widthThere will be moments when text will not be visible at all if window is not full-screened.
If text will be longer and newsFeedText
width will be greater than monitor's resolution width then transition will disappear "in half" (still being on a screen).
Duration
is not dependent on a width of newsFeedText
.Now, it's nothing worng, but if transition's fromX
and toX
were be dynamically calculated then it will result in various speeds of marquee.
How to get rid of these drawbacks?
I have managed it to work, any recalculations can happen only after transition is stopped so we cannot set its cycleCount
to Timeline.INDEFINITE
. My requirement was that I could change text inside component so there are fxml wirings:
@FXML
private Text node; // text to marquee
@FXML
private Pane parentPane; // pane on which text is placed
The code which works is:
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();
where rerunAnimation()
is:
private void rerunAnimation() {
transition.stop();
// if needed set different text on "node"
recalculateTransition();
transition.playFromStart();
}
and recalculateTransition()
is:
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));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With