我在 LineChart , AreaChart 等方面取得了成功。感谢这篇文章:JavaFX LineChart Hover Values(非常感谢Jewelsea的帮助)。
但是使用 PieChart ,我遇到了一个问题:弹出窗口正在闪烁oO
使用句法颜色: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;
}
}
问题是事件(MOUSE_ENTERED和MOUSE_EXITED)经常发出而不是一次。
Ex: 我只是放入,然后推迟,我的鼠标悬停一片。 这是控制台上的结果:
MOUSE_ENTERED : BC
MOUSE_EXITED : BC
MOUSE_ENTERED : BC
MOUSE_EXITED : BC
MOUSE_ENTERED : BC
MOUSE_EXITED : BC
MOUSE_ENTERED : BC
MOUSE_EXITED : BC
任何人都知道为什么会出现这个错误?
谢谢:)
答案 0 :(得分:1)
不是标签引起的眨眼效果?
显示标签时,表示您退出了已侦听的节点。这会导致隐藏标签。当标签消失时,它会在节点上触发鼠标输入事件,它会显示标签等
没有经过测试,只是一个想法。
caption.setTranslateX(e.getX()+10);
caption.setTranslateY(e.getY()+10);
例如(10是幻数,取决于插图等)。
答案 1 :(得分:1)
感谢大家的帮助。
@maskacovnik找到问题,@ James_D找到一个很酷的解决方案,@ ItachiUchiha将我的图片放在我的帖子上:D
现在,我的新代码。
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;
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);
//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) {
//Set Label ignores the mouse
caption.setMouseTransparent(true);
//I move Label near the mouse cursor, with a offset !
caption.setTranslateX(e.getX());
caption.setTranslateY(e.getY()+20);
//I change text of Label
caption.setText(String.valueOf(dataTemp.getPieValue()) + "\n" + dataTemp.getName());
//Change the color of popup, to adapt it to slice
if(caption.getStyleClass().size() == 4){
caption.getStyleClass().remove(3);
}
caption.getStyleClass().add(dataTemp.getNode().getStyleClass().get(2));
//I display Label
caption.setVisible(true);
}
});
//Need to add a event when the mouse move hover the slice
//If I don't the popup stay blocked on edges of the slice.
dataTemp.getNode().addEventHandler(MouseEvent.MOUSE_MOVED,
new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent e) {
//Keep Label near the mouse
caption.setTranslateX(e.getX());
caption.setTranslateY(e.getY()+20);
}
});
//When mouse exited (the slice of PieChart)
dataTemp.getNode().addEventHandler(MouseEvent.MOUSE_EXITED,
new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent e) {
//I Hide Label
caption.setVisible(false);
}
});
//Update progress
updateProgress(i++, sizeOfallElements);
}
return null;
}
};
return task;
}
}
结果如下:
答案 2 :(得分:1)
我有同样的问题,但也想确保弹出窗口可以超出图表,即当文本不适合图表时它不会被切断。这是使用工具提示而不是标签的解决方案:
ListView