我正在制作此Javafx质量计算器,该按钮由执行SwingWorker
背景线程的按钮组成,以计算某些比率或因素或Whathot。
我已经意识到,对于我的因素和主要因素计算(当我尝试找到一个数字的所有因素和主要因素时,用户输入),在进行计算后,我得到了此NullPointerException
。
这是单击按钮时执行的脚本:
public static longCalculationThread calculationThread;
//Called by the calculate button
@FXML
void callCalculation(ActionEvent event) throws IOException, InterruptedException {
Long number = 0L;
Long lowerBound = 0L;
Long higherBound = 0L;
try {
//Bunch of input verification logic here. The logic here also creates the variables for the thread bundle
//Enabling progress UI since no errors were encoundered...
excelPane.setVisible(false);
progressPane.setDisable(false);
progressPane.setVisible(true);
//Preparing threadBundle, which is just a bunch of fields out into a data holding class [not shown]
calculationThread = new longCalculationThread(threadBundle);
calculationThread.execute();
System.gc(); //For the objects of the previous calculationThread
}
}
这是longCalculationThread
的结构:
package PrimusForPC;
public class longCalculationThread extends SwingWorker<Void, Void> {
private ArrayList<Long> longResults = new ArrayList<>();
private ArrayList<String> stringResults = new ArrayList<>();
private calculationHolder.calculationType type;
private JFXProgressBar progressBar;
private Text progressText;
private GridView<String> answerGridView;
private Pane mainPane, progressPane;
private long mainNumber, lowerNum, upperNum;
private boolean shouldExport;
private ExcelWriter.spreadsheetTypes exportType;
private int excelExportLimit;
private JFXButton calcButton;
private Menu selectionMenu;
private static double acceptableAccuracy = 0.004; //The degree of accuracty for pi and phi couples
public static final double PHI = 1.6180339887498948482045;
public boolean shouldDie; //Called externally to kill the thread. Hasn't been implemented yet
longCalculationThread(threadArgumentBundle bundle){
progressBar = bundle.progressBar;
answerGridView = bundle.answerGridView;
type = bundle.type;
mainNumber = bundle.primaryNumber;
upperNum = bundle.upperNum;
lowerNum = bundle.lowerNum;
progressText = bundle.progressText;
mainPane = bundle.mainPane;
progressPane = bundle.progressPane;
exportType = bundle.exportType;
shouldExport = bundle.shouldExport;
excelExportLimit = bundle.excelExportLimit;
calcButton = bundle.button;
selectionMenu = bundle.selectionMenu;
}
@Override
public Void doInBackground(){
System.out.println("Thread started " + Thread.currentThread().getName());
Platform.runLater(new Runnable() {
@Override
public void run() {
progressBar.isIndeterminate();
progressBar.progressProperty().setValue(0);
calcButton.setDisable(true);
selectionMenu.setDisable(true);
}
});
switch (type){
case factors:
findfactors();
break;
case primeFactors:
findPrimeFactors();
break;
case primesUpToX:
findPrimesUpToX();
break;
//Bunch of other cases here...
}
try {
publishResults();
} catch (IOException | InterruptedException ex) {
Logger.getLogger(longCalculationThread.class.getName()).log(Level.SEVERE, null, ex);
}
reEndableInterface();
System.gc();
System.out.println("Thread ended " + Thread.currentThread().getName() + "n");
return null;
}
static private long getSquareRoot (long number){
//For calculations square root only matters for larger numbers
//for numbers below 5 it doesn't really matter
if (number > 5){
number = (long) Math.ceil(Math.sqrt(number));
}
return number;
}
private void findfactors(){
progressText.setText("Finding factors...");
long root = getSquareRoot(mainNumber);
double incrementValue = 1/(double)root;
for (long divisor = 1; divisor <= root; divisor++) {
setProgressBar(progressBar.getProgress() + incrementValue);
if (mainNumber % divisor == 0) {
longResults.add(divisor);
longResults.add((mainNumber/divisor));
}
}
}
private void findPrimeFactors(){
findfactors();
progressText.setText("Separating prime factors from composite factors...");
progressBar.progressProperty().set(0);
double incrementValue = 1/(double)longResults.size();
ArrayList <Long> realResults = new ArrayList<>();
for (long factor: longResults){
if (isPrime(factor)) realResults.add(factor);
setProgressBar(progressBar.getProgress() + incrementValue);
}
longResults = realResults;
}
static boolean isPrime(long number){
if (number == 1) return false;
if (number == 2 || number == 3 || number == 5) return true;
long root = getSquareRoot(number);
for (int divisor = 2; divisor <= root; divisor++)
if (number % divisor == 0) return false;
return true;
}
private void publishResults() throws IOException, InterruptedException{
Platform.runLater(new Runnable() {
@Override
public void run() {
answerGridView.getItems().setAll(stringResults);
}
});
//To make UI interface useable again
private void reEndableInterface(){
Platform.runLater(new Runnable() {
@Override
public void run() {
progressPane.setDisable(true);
progressPane.setVisible(false);
mainPane.setDisable(false);
mainPane.setVisible(true);
calcButton.setDisable(false);
System.out.println("Button enabled " + Thread.currentThread().getName());
selectionMenu.setDisable(false);
}
});
}
我不确定此NullPointerException
来自何处,或者为什么当我使用"查找因子"或"查找素数因子"计算时似乎仅出现。这是查看错误日志(对不起,这么长,不知道要切断哪里)。
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at com.sun.javafx.text.PrismTextLayout.addTextRun(PrismTextLayout.java:755)
at com.sun.javafx.text.GlyphLayout.addTextRun(GlyphLayout.java:140)
at com.sun.javafx.text.GlyphLayout.breakRuns(GlyphLayout.java:312)
at com.sun.javafx.text.PrismTextLayout.buildRuns(PrismTextLayout.java:770)
at com.sun.javafx.text.PrismTextLayout.layout(PrismTextLayout.java:1021)
at com.sun.javafx.text.PrismTextLayout.ensureLayout(PrismTextLayout.java:223)
at com.sun.javafx.text.PrismTextLayout.getBounds(PrismTextLayout.java:246)
at javafx.scene.text.Text.getLogicalBounds(Text.java:358)
at javafx.scene.text.Text.impl_computeGeomBounds(Text.java:1168)
at javafx.scene.Node.updateGeomBounds(Node.java:3577)
at javafx.scene.Node.getGeomBounds(Node.java:3530)
at javafx.scene.Node.getLocalBounds(Node.java:3478)
at javafx.scene.Node.updateTxBounds(Node.java:3641)
at javafx.scene.Node.getTransformedBounds(Node.java:3424)
at javafx.scene.Parent.getChildTransformedBounds(Parent.java:1724)
at javafx.scene.Parent.updateCachedBounds(Parent.java:1588)
at javafx.scene.Parent.recomputeBounds(Parent.java:1527)
at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1380)
at javafx.scene.layout.Region.impl_computeGeomBounds(Region.java:3078)
at javafx.scene.Node.updateGeomBounds(Node.java:3577)
at javafx.scene.Node.getGeomBounds(Node.java:3530)
at javafx.scene.Node.getLocalBounds(Node.java:3478)
at javafx.scene.Node.updateTxBounds(Node.java:3641)
at javafx.scene.Node.getTransformedBounds(Node.java:3424)
at javafx.scene.Parent.getChildTransformedBounds(Parent.java:1724)
at javafx.scene.Parent.updateCachedBounds(Parent.java:1588)
at javafx.scene.Parent.recomputeBounds(Parent.java:1527)
at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1380)
at javafx.scene.layout.Region.impl_computeGeomBounds(Region.java:3078)
at javafx.scene.Node.updateGeomBounds(Node.java:3577)
at javafx.scene.Node.getGeomBounds(Node.java:3530)
at javafx.scene.Node.getLocalBounds(Node.java:3478)
at javafx.scene.Node.updateTxBounds(Node.java:3641)
at javafx.scene.Node.getTransformedBounds(Node.java:3424)
at javafx.scene.Parent.getChildTransformedBounds(Parent.java:1724)
at javafx.scene.Parent.updateCachedBounds(Parent.java:1588)
at javafx.scene.Parent.recomputeBounds(Parent.java:1527)
at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1380)
at javafx.scene.layout.Region.impl_computeGeomBounds(Region.java:3078)
at javafx.scene.Node.updateGeomBounds(Node.java:3577)
at javafx.scene.Node.getGeomBounds(Node.java:3530)
at javafx.scene.Node.getLocalBounds(Node.java:3478)
at javafx.scene.Node.impl_intersectsBounds(Node.java:5013)
at javafx.scene.layout.Region.impl_pickNodeLocal(Region.java:2931)
at javafx.scene.Node.impl_pickNode(Node.java:4912)
at javafx.scene.layout.Region.impl_pickNodeLocal(Region.java:2936)
at javafx.scene.Node.impl_pickNode(Node.java:4912)
at javafx.scene.Scene$MouseHandler.pickNode(Scene.java:3899)
at javafx.scene.Scene$MouseHandler.access$1600(Scene.java:3485)
at javafx.scene.Scene.pick(Scene.java:1942)
at javafx.scene.Scene.access$6700(Scene.java:159)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3799)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:352)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$355(GlassViewEventHandler.java:388)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:387)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$149(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)
,然后在结尾处垃圾邮件:
java.lang.ArrayIndexOutOfBoundsException
无限期。
正如我说的,我真的不知道为什么会发生这种情况。该计算在前几次工作,然后发生此错误并冻结应用程序,需要完整的重新启动。
感谢评论我的问题的人 - 链接揭示了问题!
我正在使用摇动工人,因为我希望能够直接影响UI线程(因为程序。Runlater可以淹没UI线程,如果反复打电话经常打电话)。
事实证明,Swingworker无法在Javafx中具有该功能,因此我试图直接影响UI线程会导致这些错误。因此,我返回使用线程,并使用了评论中链接提供的节流逻辑。这使我可以使用program.runlater在线程中不淹没UI线程。