如何在Javafx Barchart中清除文本?[英] How to clear text added in a javafx barchart?

问题描述

我在条顶部添加一些文本(每个条的值).它在工作,但问题是我想每次更新图表时都要删除此文本.实际上,文本在更新数据后停留.

对于第一个图表,由于没有以前的数据正确显示. 第一个图表正确显示而没有以前的数据

但是,在更新图表的数据之后,这是我得到的(它正在工作,但先前添加的文本仍然...):

我以红色的部分突出显示了 第二个图表显示错误,并显示了前一个数据

我的完整代码可用

仍然没有答案...

谢谢!

推荐答案

我个人更喜欢子分类barchart并覆盖适当的方法.

这只是满足您需求的演示,可以完成改进,即. e.覆盖所有相关方法,文本的格式化,居中文本,调整图表区域以适合添加的文本等.但是我想您会得到漂移:

import java.util.HashMap;
import java.util.Map;

import javafx.application.Application;
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.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class BarChartSample 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";

    /**
     * Barchart with a clear button
     */
    @Override
    public void start(Stage stage) {

        final CategoryAxis xAxis = new CategoryAxis();
        final NumberAxis yAxis = new NumberAxis();
        final BarChartExt<String, Number> bc = new BarChartExt<String, Number>(xAxis, yAxis);

        bc.setTitle("Country Summary");
        xAxis.setLabel("Country");
        yAxis.setLabel("Value");

        XYChart.Series series1 = new XYChart.Series();
        series1.setName("2003");
        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));

        XYChart.Series series2 = new XYChart.Series();
        series2.setName("2004");
        series2.getData().add(new XYChart.Data(austria, 57401.85));
        series2.getData().add(new XYChart.Data(brazil, 41941.19));
        series2.getData().add(new XYChart.Data(france, 45263.37));
        series2.getData().add(new XYChart.Data(italy, 117320.16));
        series2.getData().add(new XYChart.Data(usa, 14845.27));

        XYChart.Series series3 = new XYChart.Series();
        series3.setName("2005");
        series3.getData().add(new XYChart.Data(austria, 45000.65));
        series3.getData().add(new XYChart.Data(brazil, 44835.76));
        series3.getData().add(new XYChart.Data(france, 18722.18));
        series3.getData().add(new XYChart.Data(italy, 17557.31));
        series3.getData().add(new XYChart.Data(usa, 92633.68));

        bc.getData().addAll(series1, series2, series3);

        Button clearButton = new Button("Clear");
        clearButton.setOnAction(e -> {

            bc.getData().clear();

        });

        HBox toolbar = new HBox();
        toolbar.getChildren().addAll(clearButton);

        VBox root = new VBox();
        VBox.setVgrow(bc, Priority.ALWAYS);
        root.getChildren().addAll(toolbar, bc);

        Scene scene = new Scene(root, 800, 600);

        stage.setScene(scene);
        stage.show();
    }

    /**
     * Custom barchart with text on top of bars
     *
     * @param <X>
     * @param <Y>
     */
    private static class BarChartExt<X, Y> extends BarChart<X, Y> {

        /**
         * Registry for text nodes of the bars
         */
        Map<Node, Node> nodeMap = new HashMap<>();

        public BarChartExt(Axis xAxis, Axis yAxis) {
            super(xAxis, yAxis);
        }

        /**
         * Add text for bars
         */
        @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);

                Node text = new Text(String.valueOf(item.getYValue()));
                nodeMap.put(item.getNode(), text);
                getPlotChildren().add(text);

            }

        }

        /**
         * Remove text of bars
         */
        @Override
        protected void seriesRemoved(final Series<X, Y> series) {

            for (Node bar : nodeMap.keySet()) {

                Node text = nodeMap.get(bar);
                getPlotChildren().remove(text);

            }

            nodeMap.clear();

            super.seriesRemoved(series);
        }

        /**
         * Adjust text of bars, position them on top
         */
        @Override
        protected void layoutPlotChildren() {

            super.layoutPlotChildren();

            for (Node bar : nodeMap.keySet()) {

                Node text = nodeMap.get(bar);

                text.relocate(bar.getBoundsInParent().getMinX(), bar.getBoundsInParent().getMinY() - 30);

            }

        }
    }

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

屏幕截图:

在此处输入图像说明

其他推荐答案

感谢Roland,我能够使用固定对齐来创建以下图表.由于缺乏针对此问题的建议解决方案,这可能对某人有帮助.

在此处输入图像说明

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);
            }
        }
    }
}

其他推荐答案

我只找到了一个解决方案,即在收到更新时清除每个数据的每个括号.然后,您将重建整个系列. 如下所示,它有效,但我没有检查表演.在我的环境上,它非常快:

ObservableList<Series<String, Number>> allSeries = yourBarChart.getData();
    if (updateReceived) {
        for (XYChart.Series<String, Number> series : allSeries) {
            for (XYChart.Data<String, Number> data : series.getData()) {
                Node node = data.getNode();
                Parent parent = node.parentProperty().get();
                if (parent != null && parent instanceof Group) {
                    Group group = (Group) parent;
                    group.getChildren().clear();
                }
            }
        }
        allSeries.clear();
    }

本文地址:https://www.itbaoku.cn/post/978321.html