2016-02-19 50 views
0

我正在用餅圖工作此示例。我想生成新的自定義對象時,動態每次創建數據和更新餅圖:餅圖中的更新值

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

您可以覆蓋PieChart#layoutChartChildren以在餅圖切片的標籤中顯示其他值。我修改了你的代碼來展示一個例子。爲了增加值,我使用了更新線程,但用變量「l」修改了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); 
    } 
}