1

我希望在这段代码中从循环中看到接近 200,000 行(196,608)的输出。它只打印一行。任何人都可以发现错误吗?

import java.awt.*;
import java.util.*;
import javax.swing.*;

class SwingWorkerUnicodeTest {

    private String[] fontNameArray;
    private JLabel output = new JLabel("Processing..");
    private JProgressBar progressBar = new JProgressBar();

    class CodePointDetailWorker extends SwingWorker<Object, Object> {

        private ArrayList<Character.UnicodeBlock> unicodeBlockNames;
        private ArrayList<Character.UnicodeScript> unicodeScripts;
        private int[] glyphCount = new int[fontNameArray.length];

        public CodePointDetailWorker() {
            progressBar.setVisible(true);
            Arrays.fill(glyphCount, 0);
        }

        @Override
        protected Void doInBackground() throws Exception {
            // Check for for the first 3 planes.  The next 11 are unassigned
            int pS = 3*65536;
            for (int kk = 0; kk < pS; kk++) {
                System.out.println("doInBackground " + kk + " " + pS);
                doForEveryCodePoint(kk);
            }
            return null;
        }

        @Override
        public void done() {
            output.setText("Done!");
        }

        private final void doForEveryCodePoint(final int codePoint) {
            Character.UnicodeBlock block = Character.UnicodeBlock.of(codePoint);
            if (block != null && !unicodeBlockNames.contains(block)) {
                unicodeBlockNames.add(block);
            }

            Character.UnicodeScript us = Character.UnicodeScript.of(codePoint);
            if (us == null || us.toString() == null) {
            } else {
                if (!unicodeScripts.contains(us)) {
                    unicodeScripts.add(us);
                }
            }

            // fonts - test for points in all 6 defined blocks.
            for (int ii = 0; ii < fontNameArray.length; ii++) {
                Font f = new Font(fontNameArray[ii], Font.PLAIN, 16);
                if (f.canDisplay(codePoint)) {
                    glyphCount[ii]++;
                }
            }
        }
    }

    public SwingWorkerUnicodeTest() {
        GraphicsEnvironment ge =
                GraphicsEnvironment.getLocalGraphicsEnvironment();
        fontNameArray = ge.getAvailableFontFamilyNames();
        JPanel gui = new JPanel(new BorderLayout());

        gui.add(progressBar, BorderLayout.CENTER);
        gui.add(output, BorderLayout.PAGE_END);

        CodePointDetailWorker cpdw = new CodePointDetailWorker();
        cpdw.execute();

        JOptionPane.showMessageDialog(null, gui);
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                new SwingWorkerUnicodeTest();
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency
        SwingUtilities.invokeLater(r);
    }
}

编辑

固定代码,基于前 2 个答案的建议。

它现在都实现了报告错误的重写方法,但初始化了..much 输出的数组并在进度条中显示进度。

import java.awt.*;
import java.util.*;
import javax.swing.*;

class SwingWorkerUnicodeTest {

    private JLabel output = new JLabel("Processing..");
    // Check for for the first 3 planes.  The next 11 are unassigned
    int pS = 3 * 65536;
    private JProgressBar progressBar = new JProgressBar(0, pS);

    class CodePointDetailWorker extends SwingWorker<Object, Object> {

        private ArrayList<Character.UnicodeBlock> unicodeBlockNames;
        private ArrayList<Character.UnicodeScript> unicodeScripts;
        private int[] glyphCount;
        private String[] fontNameArray;

        public CodePointDetailWorker(String[] fontNameArray) {
            this.fontNameArray = fontNameArray;
            progressBar.setVisible(true);
            glyphCount = new int[fontNameArray.length];
            Arrays.fill(glyphCount, 0);
            unicodeBlockNames = new ArrayList<Character.UnicodeBlock>();
            unicodeScripts = new ArrayList<Character.UnicodeScript>();
        }

        @Override
        protected Void doInBackground() throws Exception {
            for (int kk = 0; kk < pS; kk++) {
                if (kk % 500 == 0) {
                    progressBar.setValue(kk);
                }
                doForEveryCodePoint(kk);
            }
            progressBar.setValue(0);
            return null;
        }

        @Override
        public void done() {
            try {
                get();
                output.setText("Done!");
            } catch (Exception ex) {
                ex.printStackTrace();
                output.setText("Bad: " + ex.getMessage());
            }
        }

        private final void doForEveryCodePoint(final int codePoint) {
            Character.UnicodeBlock block = Character.UnicodeBlock.of(codePoint);
            if (block != null && !unicodeBlockNames.contains(block)) {
                unicodeBlockNames.add(block);
            }

            Character.UnicodeScript us = Character.UnicodeScript.of(codePoint);
            if (us == null || us.toString() == null) {
            } else {
                if (!unicodeScripts.contains(us)) {
                    unicodeScripts.add(us);
                }
            }

            // fonts - test for points in all 6 defined blocks.
            for (int ii = 0; ii < fontNameArray.length; ii++) {
                Font f = new Font(fontNameArray[ii], Font.PLAIN, 16);
                if (f.canDisplay(codePoint)) {
                    glyphCount[ii]++;
                }
            }
        }
    }

    public SwingWorkerUnicodeTest(String[] names) {
        JPanel gui = new JPanel(new BorderLayout());

        gui.add(progressBar, BorderLayout.CENTER);
        gui.add(output, BorderLayout.PAGE_END);

        CodePointDetailWorker cpdw = new CodePointDetailWorker(names);
        cpdw.execute();

        JOptionPane.showMessageDialog(null, gui);
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {

                GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
                String[] fontNames = ge.getAvailableFontFamilyNames();
                new SwingWorkerUnicodeTest(fontNames);
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency
        SwingUtilities.invokeLater(r);
    }
}
4

2 回答 2

3

很可能,Exception在方法中抛出了一个被抛出的东西doInBackground,很明显,这会导致它退出。

在您的done方法中,即使它没有返回任何内容,您也应该调用以确保在方法get执行期间没有出错doInBackground

@Override
public void done() {
    try {
        get();
        output.setText("Done!");
    } catch (InterruptedException | ExecutionException ex) {
        ex.printStackTrace();
        output.setText("Bad: " + ex.getMessage());
    }
}
于 2013-10-29T23:36:20.850 回答
3

你没有初始化你的ArrayLists

public CodePointDetailWorker() {
    unicodeBlockNames = new ArrayList<>();
    unicodeScripts = new ArrayList<>();
    ...
}

所以一旦遇到这个语句NPE,就会默默地抛出aSwingWorker

if (block != null && !unicodeBlockNames.contains(block)) {
                       ^---null
于 2013-10-29T23:37:55.200 回答