Context :
Hi ! I'm trying to create a little popup which display the value of slice when mouse hover, on my PieChart (with JavaFX).
I successed on my LineChart, AreaChart etc.. Thanks this post : JavaFX LineChart Hover Values (thank you so much Jewelsea for your help).
Problem (1/2) :
But with the PieChart, I have a problem : The popup is blinking oO
My code :
With syntactic color : https://bpaste.net/show/12838ad6b2e2
import java.util.ArrayList;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.chart.PieChart;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import com.alpha.client.view.nodes.stats.statsEngine.beans.ListRepere;
import com.alpha.client.view.nodes.stats.statsEngine.beans.OptionsChart;
import com.alpha.client.view.nodes.stats.statsEngine.beans.ValueStat;
/**
*
* @author Zombkey
*/
public class PieChartNode implements ChartNode {
//My personnal attributes
private ListRepere categories;
private ArrayList<ValueStat> values;
//The PieChart
private PieChart chart;
//The data of Chart, will be fill by a thread
private ObservableList<PieChart.Data> pieChartData;
//The node which contain chart and label
private Group group;
//The Label
private final Label caption;
public PieChartNode(ListRepere categories, ArrayList<ValueStat> values, OptionsChart optionsChart) {
this.categories = categories;
this.values = values;
//New Group
group = new Group();
//I must use a StackPane to place Label hover Chart
StackPane pane = new StackPane();
group.getChildren().add(pane);
//Init' PieChart
pieChartData = FXCollections.observableArrayList();
chart = new PieChart(pieChartData);
chart.setStartAngle(180.0);
//Add chart to StackPane
pane.getChildren().add(chart);
//Init Popup(Label)
caption = new Label("");
caption.setVisible(false);
caption.getStyleClass().addAll("chart-line-symbol", "chart-series-line");
caption.setStyle("-fx-font-size: 12; -fx-font-weight: bold;");
caption.setMinSize(Label.USE_PREF_SIZE, Label.USE_PREF_SIZE);
//Add Label to StackPane
pane.getChildren().add(caption);
}
@Override
public Node getNodeGraph() {
return (Node) group;
}
@Override
public Task initTaskFormat() {
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
//i and sizeOfallElements are just use for ProgressBar
int i = 0;
int sizeOfallElements = values.size();
updateProgress(i, sizeOfallElements);
//For Each ValueStat (a Personnal pojo Class), I must create a slice
for (ValueStat v : values) {
//Create the PieChart.Data and add it to ObservableList
PieChart.Data dataTemp = new PieChart.Data(v.getCategorie().getStringName(), v.getDoubleValue());
pieChartData.add(dataTemp);
//HERE, the interessante code !
//At the same way that the LineChart, I add Event when mouse entered and mouse exited.
//When mouse entered (on the slice of PieChart)
dataTemp.getNode().addEventHandler(MouseEvent.MOUSE_ENTERED,
new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent e) {
System.out.println("MOUSE_ENTERED : "+dataTemp.getName());
//I display Label
caption.setVisible(true);
//I move Label near the mouse cursor
caption.setTranslateX(e.getX());
caption.setTranslateY(e.getY());
//I hide the mouse cursor
dataTemp.getNode().setCursor(Cursor.NONE);
//I change text of Label
caption.setText(String.valueOf(dataTemp.getPieValue()) + "\n" + dataTemp.getName());
//I try to change the frame color of Label
caption.getStyleClass().add(dataTemp.getNode().getStyleClass().get(2));
}
});
//When mouse exited (the slice of PieChart)
dataTemp.getNode().addEventHandler(MouseEvent.MOUSE_EXITED,
new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent e) {
System.out.println("MOUSE_EXITED : "+dataTemp.getName());
//I Hide Label
caption.setVisible(false);
//I show the mouse cursor
dataTemp.getNode().setCursor(Cursor.DEFAULT);
}
});
//Update progress
updateProgress(i++, sizeOfallElements);
}
return null;
}
};
return task;
}
}
Problem (2/2) :
The problem is that the events (MOUSE_ENTERED and MOUSE_EXITED) are emitted, too often instead of once.
Ex : I just put in, then put off, my mouse hover a slice. Here the result on console :
MOUSE_ENTERED : BC
MOUSE_EXITED : BC
MOUSE_ENTERED : BC
MOUSE_EXITED : BC
MOUSE_ENTERED : BC
MOUSE_EXITED : BC
MOUSE_ENTERED : BC
MOUSE_EXITED : BC
Anyone know why the event bug ?
Thanks : )
It not the blinking effect caused by label?
When you shows the label, it means that you exited the node which is listened. This causes hiding the label. When label disappears, it fires the mouse entered event on the node, it shows the label etc.
Not tested, just an idea.
EDIT:
If I am right, try to avoid putting label under the mouse pointer:
For example (10 is a magic number, depends on insets etc.)