0

I'm trying to write a simple program including a javafx PieChart. The purpose of the program is that I want to show the size of every subfolder in a directory in a PieChart. Problem:

I want to simply display some data from another class in a PieChart. I transfer the data through an object of the controller class in the calc class and the other way around using matching parameters in each class. But instead of applying the data nothing happens. If I just feed some Data directly into the PieChartData List everything is working fine.

I've already tried to apply the data via endless ways but this just gave me a NullPointerError or an InvocationTargetException.

Controller:


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


Calc:


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>

I expect the code to display the double fileSizeByte and the String path from the controller class.

Steffen Moritz
  • 7,277
  • 11
  • 36
  • 55
Mr.X
  • 97
  • 1
  • 12
  • The code you posted is not quite a [mcve]. One of the things I couldn't find was the [start](https://docs.oracle.com/javase/8/javafx/api/javafx/application/Application.html#start-javafx.stage.Stage-) method. Please [edit] your question and make it a complete program that I can copy and compile and run. – Abra Jul 13 '19 at 04:36
  • MRE is essential as advised. Also there are some issues in `Calc` the main one being that every time you invoke `add` you create a new instance of `Controller`. None of the newly created `Controller` instances is the one used by the the `FXML`. – c0der Jul 13 '19 at 05:29

1 Answers1

1

When the .fxml file is loaded, an instance of Controller is constructed.
The main issue with the solution posted is that by

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

you actually setData to a new Cotroller instance, and not the one use by he controller.

A better solution would be to let Calc have a reference of the ObservableList you want to update with the calculation results:

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 
}

And use Calc in the controller like so:

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);
    }
}
c0der
  • 18,467
  • 6
  • 33
  • 65
  • I am glad it helps. I hope it explains the reason why it failed. If you post new questions (in most cases mre is essential) leave me a message here and I'll try to help. – c0der Jul 13 '19 at 08:45