更新饼图中的值

时间:2016-02-19 21:53:57

标签: javafx javafx-2

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

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

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

1 个答案:

答案 0 :(得分:1)

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

以下示例中缺少FSPartitions类。

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