更新饼图中的值 [英] Update values in Pie Chart

查看:220
本文介绍了更新饼图中的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用饼图来处理这个例子。我想动态创建数据并在每次生成新的自定义对象时更新饼图:

I'm working on this example with Pie chart. I want to create data dynamically and update Pie chart every time when new custom object is generated:

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.chart.PieChart.Data;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tooltip;
import javafx.scene.effect.Glow;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class MainApp extends Application
{

    Stage stage;

    private ObservableList<Data> pieChartdData = FXCollections.observableArrayList();
    private final PieChart chart = new PieChart(pieChartdData);
    Label caption;

    @Override
    public void start(Stage stage)
    {

        this.stage = stage;

        setUserAgentStylesheet(STYLESHEET_MODENA);
        Scene scene = new Scene(new Group());
        stage.setTitle("Imported Fruits");
        stage.setWidth(500);
        stage.setHeight(500);

        chart.setTitle("Imported Fruits");

        // Add some data
        addPieChartData("Grapefruit", 13);
        addPieChartData("Oranges", 25);
        addPieChartData("Plums", 10);
        addPieChartData("Pears", 22);
        addPieChartData("Apples", 30);

        // Some task which updates the Pie Chart
        final Task task;
        task = new Task<Void>()
        {
            @Override
            protected Void call() throws Exception
            {
                int max = 50;
                int l = 0;
                for (int i = 1; i <= max; i++)
                {

                    FSPartitions data1 = FSPartitions.newInstance().FSName("test1").FSType("test1").isReadonly(true).totalSize(3434).usedSize(333).availableSize(3644);
                    FSPartitions data2 = FSPartitions.newInstance().FSName("test2").FSType("test2").isReadonly(true).totalSize(34334).usedSize(343).availableSize(3544);
                    FSPartitions data3 = FSPartitions.newInstance().FSName("test3").FSType("test3").isReadonly(true).totalSize(34543).usedSize(353).availableSize(3446);

                    List<FSPartitions> ss = new ArrayList<>();
                    ss.add(data1);
                    ss.add(data2);
                    ss.add(data3);

                    updatePieChart(ss);

                    Thread.sleep(600);
                }
                return null;
            }
        };

        new Thread(task).start();

        ((Group) scene.getRoot()).getChildren().addAll(chart, caption);
        stage.setScene(scene);
        stage.show();
    }

    public void addPieChartData(String name, double value)
    {
        pieChartdData.add(new Data(name, value));

        caption = new Label();
        caption.setTextFill(Color.DARKORANGE);
        caption.setStyle("-fx-font: 24 arial;");

        for (final Data data : chart.getData())
        {

            Node node = data.getNode();

            node.addEventHandler(MouseEvent.MOUSE_MOVED, new EventHandler<MouseEvent>()
            {
                @Override
                public void handle(MouseEvent e)
                {
                    caption.setTranslateX(e.getSceneX() + 15);
                    caption.setTranslateY(e.getSceneY());
                    caption.setText(String.valueOf(data.getPieValue()) + "%");
                    caption.setVisible(true);
                    node.setEffect(new Glow());
                    //String styleString = "-fx-border-color: white; -fx-border-width: 1; -fx-border-style: dashed;";
                    //node.setStyle(styleString);
                }
            });

            node.addEventHandler(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>()
            {
                @Override
                public void handle(MouseEvent e)
                {
                    caption.setVisible(false);
                    node.setEffect(null);
                    //node.setStyle("");
                }
            });

            final MenuItem resizeItem = new MenuItem("Resize");
            resizeItem.setOnAction(new EventHandler<ActionEvent>()
            {
                @Override
                public void handle(ActionEvent event)
                {
                    System.out.println("Resize requested");
                }
            });

            final MenuItem aboutItem = new MenuItem("About");
            aboutItem.setOnAction(new EventHandler<ActionEvent>()
            {
                @Override
                public void handle(ActionEvent event)
                {
                    System.out.println("About requested");
                }
            });

            final MenuItem changeColorItem = new MenuItem("Change Color");
            changeColorItem.setOnAction(new EventHandler<ActionEvent>()
            {
                @Override
                public void handle(ActionEvent event)
                {
                    System.out.println("change Color Item requested");

                }
            });

            final ContextMenu menu = new ContextMenu(resizeItem, aboutItem, changeColorItem);

            node.setOnMouseClicked(new EventHandler<MouseEvent>()
            {
                @Override
                public void handle(MouseEvent event)
                {
                    if (MouseButton.SECONDARY.equals(event.getButton()))
                    {
                        menu.show(stage, event.getScreenX(), event.getScreenY());
                    }
                }
            });

        }
    }

    // updates existing Data-Object if name matches
    public void updatePieChart(List<FSPartitions> obj)
    {
        for (FSPartitions obj1 : obj)
        {
            String fsName = obj1.getFSName();
            double usedSize = obj1.getUsedSize();

            for (Data d : pieChartdData)
            {
                if (d.getName().equals(fsName))
                {
                    d.setPieValue(usedSize);
                    return;
                }
            }
        }

        pieChartdData.forEach(data
            -> data.nameProperty().bind(
                Bindings.concat(
                    data.getName(), " ", data.pieValueProperty(), " Tons"
                )
            )
        );

        for (FSPartitions obj1 : obj)
        {
            String fsName = obj1.getFSName();
            double usedSize = obj1.getUsedSize();

            pieChartdData.add(new Data(fsName, usedSize));
        }

        chart.getData().stream().forEach(data ->
        {
            Tooltip aaas = new Tooltip();
            aaas.setText(data.getPieValue() + "%");
            Tooltip.install(chart, aaas);
            data.pieValueProperty().addListener((observable, oldValue, newValue)
                -> aaas.setText(newValue + "%"));
        });

        chart.setData(pieChartdData);
    }

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

}

class FSPartitions implements Serializable
{
    private static final long serialVersionUID = 1L;
    private String FSName;
    private String FSType;
    private boolean isReadonly;
    private long totalSize;
    private long usedSize;
    private long availableSize;

    public static FSPartitions newInstance()
    {
        return new FSPartitions();
    }

    public FSPartitions()
    {
    }

    @Override
    public String toString()
    {
        return "FSName=" + FSName + ", FSType=" + FSType + ", totalSize=" + totalSize + ", usedSize=" + usedSize + ", availableSize=" + availableSize;
    }

    public FSPartitions FSName(String FSName)
    {
        this.FSName = FSName;
        return this;
    }

    public FSPartitions FSType(String FSType)
    {
        this.FSType = FSType;
        return this;
    }

    public FSPartitions isReadonly(boolean isReadonly)
    {
        this.isReadonly = isReadonly;
        return this;
    }

    public FSPartitions totalSize(long totalSize)
    {
        this.totalSize = totalSize;
        return this;
    }

    public FSPartitions usedSize(long usedSize)
    {
        this.usedSize = usedSize;
        return this;
    }

    public FSPartitions availableSize(long availableSize)
    {
        this.availableSize = availableSize;
        return this;
    }

    public String getFSName()
    {
        return FSName;
    }

    public String getFSType()
    {
        return FSType;
    }

    public boolean getIsReadonly()
    {
        return isReadonly;
    }

    public long getTotalSize()
    {
        return totalSize;
    }

    public long getUsedSize()
    {
        return usedSize;
    }

    public long getAvailableSize()
    {
        return availableSize;
    }
}

我还想为饼图添加一些额外的标签切片。看起来我需要完全重新设计代码,因为每次我将拥有不同的数据,我需要可视化数据。我怎么能这个?你能帮我实现这个吗?

I also want to add some additional labels for pie chart slice. Looks like I need to totally redesign the code because every time I will have different data and I need to to visualize the data. How I can to this? Can you help me to implement this?

推荐答案

您可以覆盖 PieChart#layoutChartChildren 以显示其他值饼图切片的标签。我修改了你的代码来展示一个例子。为了添加值,我使用了您的更新线程,但使用变量l修改了 usedSize 值,以在动画中生成更改值和标签。

You can override PieChart#layoutChartChildren to display additional values in the label of the pie chart slices. I modified your code to show an example. For adding values, I used your update thread, but modified the usedSize values with the variable "l" to produce changing values and labels in the animation.

以下示例中缺少FSPartitions类。

The FSPartitions class is missing in the below example.

public class MainApp extends Application {

  Stage                         stage;

  private ObservableList<Data>  pieChartData    = FXCollections.observableArrayList();
  private final PieChart        chart           = new PieChart(pieChartData) {
        @Override
        protected void layoutChartChildren(double top, double left, double contentWidth, double contentHeight) {
          if (getLabelsVisible()) {
            getData().forEach(d -> {
              Optional<Node> opTextNode = chart.lookupAll(".chart-pie-label").stream().filter(n -> n instanceof Text && ((Text) n).getText().contains(d.getName())).findAny();
              if (opTextNode.isPresent()) {
                ((Text) opTextNode.get()).setText(d.getName() + " " + d.getPieValue());
              }
            });
          }
          super.layoutChartChildren(top, left, contentWidth, contentHeight);
        }};

  Label                         caption         = new Label();

  @Override
  public void start(Stage stage) {

    this.stage = stage;

    setUserAgentStylesheet(STYLESHEET_MODENA);
    Scene scene = new Scene(new Group());
    stage.setTitle("File System");
    stage.setWidth(500);
    stage.setHeight(500);

    chart.setTitle("File System Size");

    // Some task which updates the Pie Chart
    final Task<Void> task = new Task<Void>() {
        @Override
        protected Void call() throws Exception {
            int max = 50;
            int l = 0;
            for (int i = 1; i <= max; i++) {

                FSPartitions data1 = FSPartitions.newInstance().FSName("test1").FSType("test1").isReadonly(true).totalSize(3434).usedSize(333+l).availableSize(3644);
                FSPartitions data2 = FSPartitions.newInstance().FSName("test2").FSType("test2").isReadonly(true).totalSize(34334).usedSize(343+(2*l)).availableSize(3544);
                FSPartitions data3 = FSPartitions.newInstance().FSName("test3").FSType("test3").isReadonly(true).totalSize(34543).usedSize(353+3*l).availableSize(3446);
                l++;

                List<FSPartitions> ss = new ArrayList<>();
                ss.add(data1);
                ss.add(data2);
                ss.add(data3);

                updatePieChart(ss);

                Thread.sleep(600);
            }
            return null;
        }
    };

    new Thread(task).start();

    ((Group) scene.getRoot()).getChildren().addAll(chart, caption);
    stage.setScene(scene);
    stage.show();
  }

  public void addPieChartData(String name, double value) {
    pieChartData.add(new Data(name, value));

    caption = new Label();
    caption.setTextFill(Color.DARKORANGE);
    caption.setStyle("-fx-font: 24 arial;");

    for (final Data data : chart.getData()) {

        Node node = data.getNode();

        node.addEventHandler(MouseEvent.MOUSE_MOVED, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent e) {
                caption.setTranslateX(e.getSceneX() + 15);
                caption.setTranslateY(e.getSceneY());
                caption.setText(String.valueOf(data.getPieValue()) + "%");
                caption.setVisible(true);
                node.setEffect(new Glow());
                // String styleString = "-fx-border-color: white;
                // -fx-border-width: 1; -fx-border-style: dashed;";
                // node.setStyle(styleString);
            }
        });

        node.addEventHandler(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent e) {
                caption.setVisible(false);
                node.setEffect(null);
                // node.setStyle("");
            }
        });

        final MenuItem resizeItem = new MenuItem("Resize");
        resizeItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                System.out.println("Resize requested");
            }
        });

        final MenuItem aboutItem = new MenuItem("About");
        aboutItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                System.out.println("About requested");
            }
        });

        final MenuItem changeColorItem = new MenuItem("Change Color");
        changeColorItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                System.out.println("change Color Item requested");

            }
        });

        final ContextMenu menu = new ContextMenu(resizeItem, aboutItem, changeColorItem);

        node.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                if (MouseButton.SECONDARY.equals(event.getButton())) {
                    menu.show(stage, event.getScreenX(), event.getScreenY());
                }
            }
        });

    }
  }

  // updates existing Data-Object if name matches
  public void updatePieChart(List<FSPartitions> obj) {
    Platform.runLater(new Runnable() {
        @Override
        public void run() {
            for (FSPartitions obj1 : obj) {
                String fsName = obj1.getFSName();
                double usedSize = obj1.getUsedSize();

                boolean found = false;
                for (Data d : pieChartData) {
                    if (d.getName().equals(fsName)) {
                        d.setPieValue(usedSize);
                        found = true;
                        break;
                    }
                }

                if (!found) {
                    addPieChartData(fsName, usedSize);
                }
            }
        }
    });
  }

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

这篇关于更新饼图中的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆