0

I am redirecting System.out.print() to a JTextArea inside of a JScrollPane. This works fine except for one case as follows in this snippet:

public void vcFile(){
System.out.println("In vcFile");    // THIS WORKS!
File[] files = getChooser("Select File(s)", JFileChooser.FILES_AND_DIRECTORIES, true);
if(files[0] != null)    {
    ...
    try {
        for(int j=0; j<files.length; j++)   {
            // SDencryptFiles() has System.out.println()'s in it, but
            // no System.out's show in the JScrollPane until after 
            // SDencryptFiles completes  I want then to appear as they
            // are executed
            SDencryptFiles(String, String, int);
        }   
    } catch (Exception e)   {
    }
}
...

Do I need to run something in the background on a separate Thread? Any ideas are appreciated.
Thanks.

MH2K9
  • 11,951
  • 7
  • 32
  • 49
Steve D
  • 3
  • 2

2 Answers2

2

Swing is a single threaded framework, this means that any operation which is run within the context of the Event Dispatching Thread, which is long running in nature or blocks for some reason (like I/O operations), will prevent the EDT from processing new events and update the UI.

See Concurrency in Swing for more details

If you're using something like How to set output stream to TextArea to redirect the System.out, then you could safely wrap the decryption process in some thing like a SwingWorker or other Thread, for example...

public class DecryptWorker extends SwingWorker {

    private File[] files;

    public DecryptWorker(File[] files) {
        this.files = files;
    }

    @Override
    protected Object doInBackground() throws Exception {
        if(files[0] != null)    {
            ...
            for (int j = 0; j < files.length; j++) {
                            // SDencryptFiles() has System.out.println()'s in it, but
                    // no System.out's show in the JScrollPane until after 
                    // SDencryptFiles completes  I want then to appear as they
                    // are executed
                    SDencryptFiles(String, String, int);
            }
        }
        return null;
    }

}

See Worker Threads and SwingWorker for more details...

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • As for me this would be exactly the same as running `SDecryptFiles` in separate thread - GUI updates should be run in `process` method not in `doInBackground` as it is done now – Antoniossss Oct 14 '14 at 03:48
  • @Antoniossss Nothing in the code is updating the UI directly, as I stated, if the OP is running the previously linked post, then the UI synchronisation is taken care of. If we move the loop or `SDencryptFiles` to the `process` method, we end up with the same problem the OP already has... – MadProgrammer Oct 14 '14 at 03:51
  • Loop inside `doInBackground`, "sysout" in `process` – Antoniossss Oct 14 '14 at 03:53
  • The `System.out` is been called within `SDencryptFiles`, which, if I understand the OP's requirements, can't be changed. If they've followed the [previous example](http://stackoverflow.com/questions/12945537/how-to-set-output-stream-to-textarea/12945678#12945678) correctly, then it won't matter, as the call to update the text area is done witin the context of the EDT... – MadProgrammer Oct 14 '14 at 03:55
  • That what would change if we ran it via `SwingWorker`? Following your explanations - nothing. Am I wrong? Or would be the same effect as running it in separate thread. – Antoniossss Oct 14 '14 at 03:58
  • I prefer `SwingWorker` as a basic example, but you just as easily use a `Thread` in this case, as the synchronisation back to the EDT is taken care of by the `OutputStream` itself – MadProgrammer Oct 14 '14 at 04:01
  • @MadProgrammer I always wanted to ask you: I've notice you always using "is been" in a present context, but those two combination of words is neither correct for present or past context. The correct present tense should be "is _being_" and the correct past tense should be "_has_ been". Is that an Aussie thing? – Paul Samsotha Oct 14 '14 at 04:32
  • 1
    @peeskillet No, that's a Mad thing ;) - English sucks, been, being, bean ... I mean, seriously... – MadProgrammer Oct 14 '14 at 04:40
  • MadProgrammer - I implemented the DecryptWorker Class and it never executes doInBackground(), it just returns which I don't understand. I'm using jre 1.7 65. I played around with it and explicitly called doInBackground() from the constructor. That obviously ran but I got the same results as before (all output was displayed at the end).I should also mention that I'm using a logging class that I wrote that writes to a file and standardOut. Even before, the logs were updated in a timely manner but not the JScrollPane. Thanks for helping out this 'crusty old UNIX/c guy'. – Steve D Oct 14 '14 at 21:09
  • @SteveD Use `execute` to get `SwingWorker` to run. Consider providing a [runnable example](https://stackoverflow.com/help/mcve) which demonstrates your problem. This will result in less confusion and better responses – MadProgrammer Oct 14 '14 at 22:19
  • @MadProgrammer Now it works great! I've made a good living progrqmming for 30 years but it was always system stuff. I'm new to GUI's. – Steve D Oct 14 '14 at 22:38
1

Any changes in GUI should be ran in separate thread (in EDT to be exact) to prevent GUI freezes etc. In your case, this is what you are witness of - frozen GUI. In order to capture Sysout and see "live" updates, every text appending in your wrapper should be done via SwingUtilities.invokeLater()

Antoniossss
  • 31,590
  • 6
  • 57
  • 99
  • Okay, that read backwards to me. `SwingUtilities.invokeLater` won't tend to make a lot of differences, other than allowing the EDT some time to breath, but if the OP is running the loop in the EDT, they'd be screwed anyway. A `SwingWorker` would be a better choice... – MadProgrammer Oct 14 '14 at 03:40
  • This would violate the main rule to not run expensive operations inside EDT. – Antoniossss Oct 14 '14 at 03:45
  • Which part? Forgive, but your answer doesn't quite read the way I think you intended it to – MadProgrammer Oct 14 '14 at 03:46
  • I just pointed it out - to run expensive code inside EDT (events) – Antoniossss Oct 14 '14 at 03:49
  • Should you be running expensive code OUTside the EDT, thus allowing the EDT to continue processing events? Okay, I think I see where the confusion is coming from. The OP has used a technique of redirecting the `System.out` so it prints to the a `JTextArea`, which, I hope, they got from [this example](http://stackoverflow.com/questions/12945537/how-to-set-output-stream-to-textarea/12945678#12945678). What they need to do is take the time consuming process of looping over the files and decrypting them to a different thread. If they've synchronised the `OutputStream`, they should be right... – MadProgrammer Oct 14 '14 at 03:54
  • I think, that the problem is in wrong assumptions. And YES - expensive code should be run OUTSIDE EDT - that is the main rule of building efficient GUI. SwingWorker is the shortcut to do that. – Antoniossss Oct 14 '14 at 03:55
  • As I said, the answer "read" backwards to me, doesn't make it wrong, just made me question it ;) – MadProgrammer Oct 14 '14 at 03:57
  • To be honest with you I simply don't understand that part. But thats ok – Antoniossss Oct 14 '14 at 04:00
  • I read *"Any changes in GUI should be ran in separate thread"* and thought, *"No, it should be run within the EDT"*...which threw me ;) - It makes it sound like updates to the UI should be run in another thread, OTHER than the EDT - but as I say, that's just me ;) – MadProgrammer Oct 14 '14 at 04:02
  • `Any changes in GUI should be ran in separate thread (in EDT to be exact)` That is what I have stated from the beginning. But thanks for the explanation, now I know which part was wrong for you. – Antoniossss Oct 14 '14 at 04:05
  • Yeah, I think what you're saying is correct, it just reads "weird" to me...could be all the cold medication I'm on :P – MadProgrammer Oct 14 '14 at 04:07
  • Or just my english. Everything is explained fine by now. End of topic – Antoniossss Oct 14 '14 at 04:08