Javafx PieChart 不应用数据(有时是 NullPointerError)

Javafx PieChart doesn't apply Data (sometimes NullPointerError)

我正在尝试编写一个包含 javafx PieChart 的简单程序。 该程序的目的是我想在 PieChart 中显示目录中每个子文件夹的大小。问题:

我只想在饼图中显示来自另一个 class 的一些数据。我通过 calc class 中控制器 class 的对象传输数据,反之亦然,在每个 class 中使用匹配参数。但是没有应用数据,什么也没有发生。如果我只是将一些数据直接输入到 PieChartData 列表中,一切正常。

我已经尝试通过无数种方式应用数据,但这只会给我一个 NullPointerError 或 InvocationTargetException。

控制器:


package sample;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.chart.PieChart;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;

import java.io.File;
import java.nio.file.Path;

public class Controller {
    Calc calc = new Calc();

    @FXML
    public PieChart pieChart;
    public Button browse;
    public Button apply;
    public TextField pathField;

    String[] locs = new String[1000];
    double[] sizes = new double[1000];
    int count = 0;

    ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList();

    public void handleBrowse(){
        pathField.setText("C:\Users\user\Desktop\Test");
    }
    public void apply(){
        System.out.println(pathField.getText());
        String strings = new String(pathField.getText());
        calc.main(strings);
        System.out.println("2");
        pieChart.setData(pieChartData);
    }
    public void setData(String loc, long size, int i, int aim){
        pieChartData.add(new PieChart.Data(loc,size));
        System.out.println("1");
    }


}
//alt+Enter = Import


计算:


package sample;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;

public class Calc {
    public int totalFolder=0;
    public int totalFile=0;
    public static int counter = 0;


    public void main(String args) {

        File nativeFile = new File(args);
        File file = new File(nativeFile.toString());

        String[] files = file.list();
        Path path;
        Main main = new Main();

        if(file.isDirectory()) {
            for(int i=0; i<=files.length-1; i++) {

                path = Paths.get(files[i]);
                file = path.toFile();
                System.out.println(file + " (source: Main.java)");
                counter ++;
            }
            String[] paths = new String[counter];

            for(int i=0; i<=files.length-1; i++) {

                path = Paths.get(files[i]);
                file = path.toFile();
                paths[i] = file.toString();
            }
            System.out.println("");
            for(int i=0; i!=counter; i++) {

            }
            for(int i = 0; i+1 <= paths.length; i++) {
                try {

                    Calc size = new Calc();
                    long fileSizeByte = size.getFileSize(new File(nativeFile.toString() + "\" + paths[i]));
                    System.out.println("Folder Size of " + paths[i] + " is: " + fileSizeByte / 1073741824 + " GB" + " or " + fileSizeByte + " bytes");
                    add(paths[i],fileSizeByte,i,paths.length);
                } catch (Exception e) {
                    System.out.println("failure");
                    e.printStackTrace();
                }
            }
        }

    }

    public void add(String loc, long size, int i, int aim){
        Controller controller = new Controller();
        controller.setData(loc,size,i,aim);
    }



    public long getFileSize(File folder) {
        long foldersize = 0;

        totalFolder++;
//          System.out.println("Folder: " + folder + "  (Source: getFileSize)");
        File[] filelist = folder.listFiles();
//          System.out.println(folder.listFiles());

        for (int i = 0; i < filelist.length; i++) {
            if (filelist[i].isDirectory()) {
                foldersize += getFileSize(filelist[i]);
            } else {
                totalFile++;
                foldersize += filelist[i].length();
            }
        }

        return foldersize;

    }

    public int getTotalFolder() {
        return totalFolder;
    }

    public int getTotalFile() {
        return totalFile;
    }
}


sample.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.chart.PieChart?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="900.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
   <children>
      <PieChart fx:id="pieChart" layoutX="348.0" layoutY="50.0" prefHeight="500.0" prefWidth="500.0" title="Subfolders" />
      <Separator layoutX="316.0" layoutY="-18.0" orientation="VERTICAL" prefHeight="633.0" prefWidth="0.0" />
      <TextField fx:id="pathField" focusTraversable="false" layoutX="31.0" layoutY="115.0" prefHeight="26.0" prefWidth="188.0" promptText="Type Path                                 or" />
      <Button fx:id="browse" layoutX="222.0" layoutY="115.0" mnemonicParsing="false" onAction="#handleBrowse" prefHeight="26.0" prefWidth="65.0" text="Browse" />
      <Label layoutX="116.0" layoutY="41.0" text="Options">
         <font>
            <Font size="27.0" />
         </font>
      </Label>
      <Button fx:id="apply" layoutX="31.0" layoutY="159.0" mnemonicParsing="false" onAction="#apply" prefHeight="55.0" prefWidth="256.0" text="Apply" />
   </children>
</AnchorPane>

我希望代码显示来自控制器的双 fileSizeByte 和字符串路径 class。

加载.fxml文件时,会构造Controller的一个实例。
发布的解决方案的主要问题是

public void add(String loc, long size, int i, int aim){
     Controller controller = new Controller();
     controller.setData(loc,size,i,aim);
}

你实际上 setData 到一个新的 Cotroller 实例,并且 不是 控制器使用的实例。

更好的解决方案是让 Calc 参考您要使用计算结果更新的 ObservableList

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import javafx.collections.ObservableList;
import javafx.scene.chart.PieChart;

public class Calc {

    private int totalFolder=0, totalFile=0;
    private static int counter = 0;
    private final ObservableList<PieChart.Data> pieChartData;

    //added a constructor to receive a reference of the Observable list
    public Calc(ObservableList<PieChart.Data> pieChartData) {
        this.pieChartData = pieChartData;
    }

    /*
     * This method is copied from the original method called main.
     * The use of the name main is confusing.
     * The calculation done in this method has some issues, but it is not relevant
     * to the question asked.
     */
    public void calcSubfoldersSize(String sPath) { //replaces public void main(String args)

        File nativeFile = new File(sPath);
        File file = new File(nativeFile.toString());

        String[] files = file.list();
        Path path;

        if(file.isDirectory()) {
            for(int i=0; i<=files.length-1; i++) {
                path = Paths.get(files[i]);
                file = path.toFile();
                counter ++;
            }

            String[] paths = new String[counter];
            for(int i=0; i<=files.length-1; i++) {
                path = Paths.get(files[i]);
                file = path.toFile();
                paths[i] = file.toString();
            }

            for(int i=0; i!=counter; i++) {

            }
            for(int i = 0; i+1 <= paths.length; i++) {
                try {
                    Calc size = new Calc(pieChartData); //the only line changed in the method
                    long fileSizeByte = size.getFileSize(new File(nativeFile.toString() + "\" + paths[i]));
                    add(paths[i],fileSizeByte,i,paths.length);
                } catch (Exception e) {
                    System.out.println("failure");
                    e.printStackTrace();
                }
            }
        }
    }

    //let add update the observable list
    public void add(String loc, long size, int i, int aim){
        pieChartData.add(new PieChart.Data(loc,size));
    }

    //no change in other methods 
}

并在控制器中使用 Calc,如下所示:

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.chart.PieChart;
import javafx.scene.control.TextField;

public class Controller {

    @FXML
    private PieChart pieChart;

    @FXML
    private TextField pathField;

    private ObservableList<PieChart.Data> pieChartData;
    private Calc calc;

    @FXML
    void initialize(){
        pieChartData = FXCollections.observableArrayList();
        calc = new Calc( pieChartData);
        pieChart.setData(pieChartData);
    }

    @FXML
    private void handleBrowse(){
        pathField.setText("C:/Users/user/Desktop/Test");
    }

    @FXML
    private void apply(){
        String strings = new String(pathField.getText());
        calc.calcSubfoldersSize(strings);
    }
}