I expected to see close to 200,000 lines (196,608) of output from the loop in this code. It only prints one line. Can anyone spot the blunder?
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);
}
}
Fixed code, based on the advice of the first 2 answers.
It now both implements the overridden method that reports errors, but initializes the arrays for ..much output and shows progress in the progress bar.
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);
}
}
There is, likely, an Exception
being thrown within the doInBackground
method, which is, obviously, causing it to exit.
In your done
method, even if it returns nothing, you should call get
to ensure that nothing went wrong during the execution of the doInBackground
method
@Override
public void done() {
try {
get();
output.setText("Done!");
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace();
output.setText("Bad: " + ex.getMessage());
}
}