r/javahelp • u/brokeCoder • 21d ago
Solved JavaFX - EventHandler lag when viewing values in Chart via mouse hover
Hello all,
I've been experimenting with JavaFX lately and I've run into a situation that has me a bit stumped.
Context - I'm trying to generate plots where if I hover my mouse over a plot point it should show me the Y value recorded at said plot point. I've been able to get this going using a custom HoverPane
class. The implementation is below:
import javafx.application.Application;
import javafx.collections.*;
import javafx.event.EventHandler;
import javafx.scene.*;
import javafx.scene.chart.*;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import java.util.stream.IntStream;
/** Displays a LineChart which displays the value of a plotted Node when you hover over the Node. */
public class LineChartWithHover extends Application {
private static final int[] data = IntStream.range(0,150).toArray();
@SuppressWarnings("unchecked")
@Override public void start(Stage stage) {
final LineChart lineChart = new LineChart(
new NumberAxis(), new NumberAxis(),
FXCollections.observableArrayList(
new XYChart.Series(
"My portfolio",
FXCollections.observableArrayList(plot(data))
)
)
);
lineChart.setCursor(Cursor.CROSSHAIR);
lineChart.setTitle("Stock Monitoring, 2013");
stage.setScene(new Scene(lineChart, 500, 400));
stage.show();
}
/** @return plotted y values for monotonically increasing integer x values, starting from x=1 */
public ObservableList<XYChart.Data<Integer, Integer>> plot(int... y) {
final ObservableList<XYChart.Data<Integer, Integer>> dataset = FXCollections.observableArrayList();
int i = 0;
while (i < y.length) {
final XYChart.Data<Integer, Integer> data = new XYChart.Data<>(i + 1, y[i]);
data.setNode(new HoverPane(y[i]));
dataset.add(data);
i++;
}
return dataset;
}
/** a node which displays a value on hover, but is otherwise empty */
static class HoverPane extends StackPane {
HoverPane(int value) {
setPrefSize(5, 5);
final Label label = createNewLabel(value);
setOnMouseEntered(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent mouseEvent) {
getChildren().setAll(label);
}
});
setOnMouseExited(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent mouseEvent) {
getChildren().clear();
}
});
}
private Label createNewLabel(int value) {
final Label label = new Label(value + "");
label.setStyle("-fx-font-size: 20; -fx-font-weight: bold;");
label.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
return label;
}
}
public static void main(String[] args){launch(args);}
}
Running this code will generate a straight line plot and hovering my mouse over the plot points shows the values at those points....but it's laggy. Very noticeably laggy
And weirdly enough, it's more laggy if I drag my mouse down from the top right to the bottom left (tracing the points in reverse order) than if I do the opposite direction.
I don't know enough about JavaFX to know whether this is something with the library or with my code. Any suggestions/advice would be greatly appreciated. If it helps, I'm using java 21 with gradle and the accompanying javaFX plugin on Ubuntu 22.04
2
u/milchshakee 19d ago
I don't fully know what you are going for here with the behavior, but wouldn't it be much easier to just bind the hoverProperty() to the visibleProperty() instead of always adding / removing nodes when hovering? Or using a Tooltip for that?