是否有可能获得创建CategoryAxis类别的图表(特别是BarChart)创建的节点(列表)?
目标是为节点添加一些鼠标事件。
我试图通过xAxis.getChildrenUnmodifiable()
访问它们,但这会返回刻度线。
还有xAxis.getCategories()
但这会返回String
类别的标签文字,并添加我需要的鼠标事件Nodes
。
所以这里有一些代码可以重现我想要完成的事情:
import java.util.HashMap;
import java.util.Map;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Point2D;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.Axis;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;
public class Main extends Application {
final static String austria = "Austria";
final static String brazil = "Brazil";
final static String france = "France";
final static String italy = "Italy";
final static String usa = "USA";
@Override
public void start(Stage stage) {
Group group = new Group();
stage.setTitle("Bar Chart Sample");
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis();
final CustomBarChart<String, Number> bc =
new CustomBarChart<String, Number>(xAxis, yAxis);
bc.setTitle("Country Summary");
bc.setLegendVisible(false);
xAxis.setLabel("Country");
xAxis.setTickLabelRotation(90);
yAxis.setLabel("Value");
XYChart.Series series1 = new XYChart.Series();
series1.getData().add(new XYChart.Data(austria, 25601.34));
series1.getData().add(new XYChart.Data(brazil, 20148.82));
series1.getData().add(new XYChart.Data(france, 10000));
series1.getData().add(new XYChart.Data(italy, 35407.15));
series1.getData().add(new XYChart.Data(usa, 12000));
final Label tooltipXAxis = new Label("");
tooltipXAxis.setStyle("-fx-font-size: 12;" +
"-fx-font-weight: bold;" +
"-fx-padding: 5px;" +
"-fx-background-color: white;" +
"-fx-background-radius: 5;" +
"-fx-border-radius: 5;" +
"-fx-border-style: solid;" +
"-fx-border-width: 2;" +
"-fx-border-color: black;");
tooltipXAxis.setVisible(false);
//xAxis tooltip
for (Node n : xAxis.getChildrenUnmodifiable()) {
n.addEventHandler(MouseEvent.MOUSE_ENTERED,
new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent e) {
tooltipXAxis.setMouseTransparent(true);
tooltipXAxis.setText("Tooltip Here");
tooltipXAxis.setVisible(true);
}
});
n.addEventHandler(MouseEvent.MOUSE_MOVED,
new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent e) {
Point2D locationInScene = new Point2D(e.getSceneX(), e.getSceneY()-35);
Point2D locationInParent = group.sceneToLocal(locationInScene);
tooltipXAxis.relocate(locationInParent.getX(), locationInParent.getY());
}
});
n.addEventHandler(MouseEvent.MOUSE_EXITED,
new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent e) {
tooltipXAxis.setVisible(false);
}
});
}
bc.getData().addAll(series1);
group.getChildren().addAll(bc, tooltipXAxis);
Scene scene = new Scene(group);
stage.setScene(scene);
stage.show();
}
public class CustomBarChart<X, Y> extends BarChart<X, Y> {
Map<Node, TextFlow> nodeMap = new HashMap<>();
public CustomBarChart(Axis xAxis, Axis yAxis) {
super(xAxis, yAxis);
this.setBarGap(0.0);
}
@Override
protected void seriesAdded(Series<X, Y> series, int seriesIndex) {
super.seriesAdded(series, seriesIndex);
for (int j = 0; j < series.getData().size(); j++) {
Data<X, Y> item = series.getData().get(j);
Text text = new Text(item.getYValue().toString());
text.setStyle("-fx-font-size: 10pt;");
TextFlow textFlow = new TextFlow(text);
textFlow.setTextAlignment(TextAlignment.CENTER);
nodeMap.put(item.getNode(), textFlow);
this.getPlotChildren().add(textFlow);
}
}
@Override
protected void seriesRemoved(final Series<X, Y> series) {
for (Node bar : nodeMap.keySet()) {
Node text = nodeMap.get(bar);
this.getPlotChildren().remove(text);
}
nodeMap.clear();
super.seriesRemoved(series);
}
@Override
protected void layoutPlotChildren() {
super.layoutPlotChildren();
for (Node bar : nodeMap.keySet()) {
TextFlow textFlow = nodeMap.get(bar);
if (bar.getBoundsInParent().getHeight() > 30) {
((Text) textFlow.getChildren().get(0)).setFill(Color.WHITE);
textFlow.resize(bar.getBoundsInParent().getWidth(), 200);
textFlow.relocate(bar.getBoundsInParent().getMinX(), bar.getBoundsInParent().getMinY() + 10);
} else {
((Text) textFlow.getChildren().get(0)).setFill(Color.GRAY);
textFlow.resize(bar.getBoundsInParent().getWidth(), 200);
textFlow.relocate(bar.getBoundsInParent().getMinX(), bar.getBoundsInParent().getMinY() - 20);
}
}
}
}
public static void main(String[] args) {
launch(args);
}
}
此代码存在的问题是,当勾选标记或xAxis标签悬停时,会显示标签tooltipXAxis
。
但是,目标是在类别标签悬停时显示它,如上图所示。