I've made myself a convenient little method here that I use to spawn a floating piece of text at a given coordinate in my GUI.
public static void spawnLabel(final String text, final Color color, final double x, final double y) {
final Popup pc = new Popup();
final Label label = new Label(text);
pc.getScene().setRoot(new AnchorPane(label));// Add label to Popup
/* Style label */
label.setTextFill(color);
label.setBackground(null);
label.setStyle("-fx-font-weight: bold;");
/* Set Popup positions */
pc.setX(0);
pc.setY(0);
final TranslateTransition translateTransition = new TranslateTransition(Duration.seconds(2), label);
translateTransition.setFromY(y);
translateTransition.setFromX(x);
translateTransition.setToX(x);
translateTransition.setToY(y - 25);
translateTransition.setInterpolator(Interpolator.EASE_OUT);
final FadeTransition opacityTransition = new FadeTransition(Duration.seconds(2), label);
opacityTransition.setFromValue(0.7);
opacityTransition.setToValue(0.0);
pc.show(stage);// Uses the Stage of my app.
translateTransition.play();
opacityTransition.play();
opacityTransition.setOnFinished(event -> pc.hide());
}
It simply takes in some text, a color, and a location and spawns a piece of text wherever the location is. The text will have the given color and will say whatever is passed into this method. This all works fine and uses a Popup
object as a window and a Label
object as the text node. The text will slowly move upwards and fade away.
Here's an image of the text that shows up:
The problem I'm getting is that when the method is called multiple times, the program begins to "lag". (Usually 4-5 calls is enough to make the "lag" heavy.) What I mean by "lag" is that certain functions, like pressing buttons or hovering over some nodes, is greatly delayed.
For production, I plan to use this method quite intensively, so I can't afford to have a slight delay in common functions. I don't know what causes this lag nor how to get rid of it and I haven't found anything on google, so I've come here.
Edit 1: After repeatedly calling my method via a Button
node in my GUI, the following exception occurs at random AND my hovering text stops showing up:
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at javafx.stage.Window$TKBoundsConfigurator.apply(Window.java:1274)
at javafx.stage.Window$TKBoundsConfigurator.pulse(Window.java:1290)
at com.sun.javafx.tk.Toolkit.lambda$runPulse$30(Toolkit.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:354)
at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:378)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:510)
at com.sun.javafx.tk.quantum.PaintCollector.liveRepaintRenderJob(PaintCollector.java:320)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$ViewEventNotification.run(GlassViewEventHandler.java:831)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$ViewEventNotification.run(GlassViewEventHandler.java:792)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleViewEvent$368(GlassViewEventHandler.java:871)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleViewEvent(GlassViewEventHandler.java:870)
at com.sun.glass.ui.View.handleViewEvent(View.java:539)
at com.sun.glass.ui.View.notifyResize(View.java:875)
at com.sun.glass.ui.win.WinWindow._setBounds(Native Method)
at com.sun.glass.ui.Window.setBounds(Window.java:572)
at com.sun.javafx.tk.quantum.WindowStage.setBounds(WindowStage.java:317)
at javafx.stage.Window$TKBoundsConfigurator.apply(Window.java:1274)
at javafx.stage.Window$TKBoundsConfigurator.pulse(Window.java:1290)
at com.sun.javafx.tk.Toolkit.lambda$runPulse$30(Toolkit.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:354)
at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:378)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:510)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490)
at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$404(QuantumToolkit.java:319)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
at java.lang.Thread.run(Unknown Source)
Edit 2: I have not found exactly what causes this lag, but I have found a workaround that lets me get rid of it. I figured out that the lag persists when a Pane
of any kind is placed in the setRoot(...)
call of the fourth line of my method. I used an AnchorPane
there as a wrapper for my label
since the label
wouldn't display when passed in directly. When I removed the AnchorPane
, the lag disappeared.
Anyways, after repeated tries, I got the text to display in the Popup
without an AnchorPane
wrapper. My method is now as follows:
/**
* Spawns a floating piece of text that flies upwards a little then
* disappears. The source point of the text is specified via the {@code x}
* and {@code y} parameters.
*
* @param text
* The text to render.
* @param color
* The color of the rendered text.
* @param x
* The starting x position of the text.
* @param y
* The starting y position of the text.
*/
public static void spawnLabel(final String text, final Color color, final double x, final double y) {
final Popup pc = new Popup();
final Label label = new Label(text);
final TranslateTransition translateTransition = new TranslateTransition(Duration.seconds(2), label);
final FadeTransition opacityTransition = new FadeTransition(Duration.seconds(2), label);
pc.getScene().setRoot(label);
/* Style label */
label.setTextFill(color);
label.setBackground(null);
label.setStyle("-fx-font-weight: bold;");
/* Set Popup positions */
pc.setX(x);
pc.setWidth(label.getMaxWidth());
pc.setY(y - 50);
/* Build transitions */
translateTransition.setFromY(30);
translateTransition.setFromX(0);
translateTransition.setToX(0);
translateTransition.setToY(5);
translateTransition.setInterpolator(Interpolator.EASE_OUT);
opacityTransition.setFromValue(0.7);
opacityTransition.setToValue(0.0);
opacityTransition.setOnFinished(e -> pc.hide());
/* Show the Popup */
pc.show(stage);
pc.setHeight(50);
/* Play the transitions */
translateTransition.play();
opacityTransition.play();
}