JavaFX区域图表并在光标后添加动态标签

时间:2015-03-20 17:51:58

标签: layout charts javafx

我希望能够在光标后面的图表中添加标签。我已经在堆栈溢出上看到了几个这样的例子,它们已将标签附加到一个系列的值/节点,但我希望能够为整个区域图表执行此操作。当我想添加一个标签(最终是一个浮动的值框)时,我的问题出现了。我正在努力弄清楚如何做到这一点并保持场景的布局。当我将图表作为专用项目添加到场景时,图表按预期呈现。但是,当我向场景添加标签时,它会被共享,而图表不再填充整个画布

Group root = new Group();
root.getChildren().addAll(sac,myLabel);
Scene scene = new Scene(root, 800, 600); // Now the Chart shares the scene with the label

我想添加标签,以便我可以在鼠标移动到图表上时使用它,然后将其简单地转换为光标位置。我对鼠标事件没有任何问题,因为我似乎无法与瞬态对象共享场景。我认为这归结于对如何管理这种特殊情况缺乏了解。这个问题的解决方案很可能是动态生成此标签而不是将其作为静态场景对象。任何帮助都感激不尽。

下面的完整测试用例(Java 8)

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.StackedAreaChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;

public class AreaChartTestCase extends Application {

    final NumberAxis xAxis = new NumberAxis(1, 31, 1);
    final NumberAxis yAxis = new NumberAxis();
    final StackedAreaChart<Number, Number> sac
            = new StackedAreaChart<Number, Number>(xAxis, yAxis);
    Label myLabel = new Label();

    @Override
    public void start(Stage stage) {
        stage.setTitle("Area Chart Sample");
        sac.setTitle("Temperature Monitoring (in Degrees C)");
        XYChart.Series<Number, Number> seriesApril
                = new XYChart.Series<Number, Number>();
        seriesApril.setName("April");
        seriesApril.getData().add(new XYChart.Data(1, 4));
        seriesApril.getData().add(new XYChart.Data(3, 10));
        seriesApril.getData().add(new XYChart.Data(6, 15));
        seriesApril.getData().add(new XYChart.Data(9, 8));
        seriesApril.getData().add(new XYChart.Data(12, 5));
        seriesApril.getData().add(new XYChart.Data(15, 18));
        seriesApril.getData().add(new XYChart.Data(18, 15));
        seriesApril.getData().add(new XYChart.Data(21, 13));
        seriesApril.getData().add(new XYChart.Data(24, 19));
        seriesApril.getData().add(new XYChart.Data(27, 21));
        seriesApril.getData().add(new XYChart.Data(30, 21));
        XYChart.Series<Number, Number> seriesMay
                = new XYChart.Series<Number, Number>();
        seriesMay.setName("May");
        seriesMay.getData().add(new XYChart.Data(1, 20));
        seriesMay.getData().add(new XYChart.Data(3, 15));
        seriesMay.getData().add(new XYChart.Data(6, 13));
        seriesMay.getData().add(new XYChart.Data(9, 12));
        seriesMay.getData().add(new XYChart.Data(12, 14));
        seriesMay.getData().add(new XYChart.Data(15, 18));
        seriesMay.getData().add(new XYChart.Data(18, 25));
        seriesMay.getData().add(new XYChart.Data(21, 25));
        seriesMay.getData().add(new XYChart.Data(24, 23));
        seriesMay.getData().add(new XYChart.Data(27, 26));
        seriesMay.getData().add(new XYChart.Data(31, 26));

        final Node chartPlotBackground = sac.lookup(".chart-plot-background");
        chartPlotBackground.setOnMouseEntered((MouseEvent mouseEvent) -> {
            myLabel.setVisible(true);
        });

        chartPlotBackground.setOnMouseExited((MouseEvent mouseEvent) -> {
            myLabel.setVisible(false);
        });

        chartPlotBackground.setOnMouseMoved((MouseEvent mouseEvent) -> {
            myLabel.setText("Location : X = " + mouseEvent.getSceneX() + " : Y = "+ mouseEvent.getSceneY());
            myLabel.setTranslateX(mouseEvent.getSceneX());
            myLabel.setTranslateY(mouseEvent.getSceneY());
        });

        Group root = new Group();
        root.getChildren().addAll(sac, myLabel);
        Scene scene = new Scene(root, 800, 600); // Now the Chart shares the scene with the label
        sac.getData().addAll(seriesApril, seriesMay);
        stage.setScene(scene);
        stage.show();

    }

    public static void main(String[] args) {
        launch(args);
    }
}

1 个答案:

答案 0 :(得分:0)

所以我想我已经解决了。至少达到符合我要求的水平。

    Group root = new Group();
    root.setManaged(false);
    root.getChildren().add(ac);
    root.getChildren().add(myLabel);
    Scene scene = new Scene(root);

    scene.widthProperty().addListener(new ChangeListener<Number>() {
        @Override
        public void changed(ObservableValue<? extends Number> observableValue, Number oldSceneWidth, Number newSceneWidth) {
            ac.setPrefWidth((double) newSceneWidth);
        }
    });
    scene.heightProperty().addListener(new ChangeListener<Number>() {
        @Override
        public void changed(ObservableValue<? extends Number> observableValue, Number oldSceneHeight, Number newSceneHeight) {
            ac.setPrefHeight((double) newSceneHeight);
        }
    });

通过收听宽度和高度属性的变化并手动管理图表和标签的布局,我能够获得我需要的布局和功能。我不是百分之百确定这是否是最佳方法但是它有效