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);
}
}
我正在尝试编写一个包含 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);
}
}