views:

27

answers:

1

In Java, I have a package that translates XML metadata from one standard to another. This package is ultimately accessed through a single function and sends all of its output through a PrintStream object. The output sent is just a status of each file and whether or not it was translated.

This is pretty fine and dandy if I'm just printing to System.out, but I'm actually wanting to print this to a JTextPane while it translates (kind of like a progress text box). It wouldn't be a big deal to just print the status after it was done translating the XML, but since there may be thousands of XML files, that's just not feasible.

One thing that I've tried is to use a thread that takes all of the information from the PrintStream (which is attached to a ByteArrayOutputStream) and let it send any new information to the text pane. Unfortunately, this still sends the information all at once at the end of the translation. This does work correctly for System.out.

Here's the code that does the translation and tries to show the output:

public class ConverterGUI extends javax.swing.JFrame {

    boolean printToResultsBox = false;
    PrintStream printStream = null;
    ByteArrayOutputStream baos = null;

    private class ResultsPrinter implements Runnable {

        public ResultsPrinter() {
            baos = new ByteArrayOutputStream();
            printStream = new PrintStream(baos);
        }

        public void run() {
            String tempString = "";
            while (printToResultsBox) {
                try {
                    if (!baos.toString().equals(tempString)) {
                        tempString = baos.toString();
                        resultsBox.setText(tempString);
                    }
                } catch (Exception ex) {
                }
            }
        }
    }

    ...

    ResultsPrinter rp = new ResultsPrinter();
    Thread thread = new Thread(rp);
    thread.start();

    // Do the translation.
    try {
        printToResultsBox = true;
        boolean success = false;
        TranslationEngine te = new TranslationEngine();
        // fileOrFolderToConvert is a text box in the GUI.
        // linkNeeded and destinationFile are just parameters for the translation process.
        success = te.translate(fileOrFolderToConvert.getText(), linkNeeded, destinationFile, printStream);
        if (success) {
            printStream.println("File/folder translation was a success.");
        }
        resultsBox.setText(baos.toString());
    } catch (Exception ex) {
        printStream.println("File translation failed.");
    } finally {
        printToResultsBox = false;
    }

    ...

}

Ultimately, this code prints out to the JTextPane just fine after all the translation is done but not during. Any suggestions? Do I need to change the PrintStream to something else?

+1  A: 

The problem with the way your thread works is you are not on the UI event thread when updating your results box. Take a look at the SwingWorker class. Or you could even use the SwingUtilities.invokeAndWait

broschb