在swingworker上调用execute()时,神秘的nullpointerexception



我正在制作此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线程。

相关内容

最新更新