0

I've been told that I need to create a SwingWorker for a long-running directory tree walker whose "guts" are shown in pieces below. (To keep it short, I've removed lots of closing } and ) and other superfluous (to my question) stuff such as ignored catch clauses.)

When matching a given filename pattern, a filename (and other stuff) is written, by report(), to a text area:

public class TASK extends SimpleFileVisitor<Path> implements Runnable{
  public static FileVisitResult disposition = FileVisitResult.CONTINUE;

  private static void report(String s){
      try{
        Output.jTextArea1.append(s + "\n");
      catch (Exception e){ aborted = true ; disposition = FileVisitResult.TERMINATE;} 

  public void run() {
      disposition = FileVisitResult.CONTINUE;
      Files.walkFileTree(p , this); // walkTreeFile calls visitFile() for each file.

  public FileVisitResult visitFile(Path f, BasicFileAttributes a) throws IOException {
    report(f1.getFileName().toString());
    return disposition;

main() just creates threads for GUI and Output:

  public static void main(String args[]) {          // main
    java.awt.EventQueue.invokeLater(new Runnable() {
      public void run() { 
        gui = new GUI();
        gui.setVisible(true); 

    java.awt.EventQueue.invokeLater(new Runnable() {
      public void run() {
        info = new Output();

When the "Search" button is clicked jbSearch...() makes the output window visible and instantiates TASK and the tree walk begins:

  private void jbSearchActionPerformed(ActionEvent evt) {   // this is in GUI
      try {
        TASK v = new TASK();
        Thread t = new Thread(v);
        t.start();

It all works fine BUT the output window flickers and looks hacked, so I need SwingWorker. But I can't say the following because TASK (or something) has to extend SimpleFileVisitor:

  class TASK extends SwingWorker<List<String>, String> 

So I'm looking for something to implement. My notes tell me "Because SwingWorker implements Runnable, a SwingWorker can be submitted to an Executor for execution" so I think I'm heading there next unless somebody stops me! (I've never used executors before.)

After I figure out how in involve SwingWorker, I assume I should do the following, probably in jbSearch...() in place of the 3 lines shown (just above):

  TASK.execute();

I guess I have to make doInBackground() call visitFile(), which is what is applied to all the files in the walk. Is it MY responsibility to fill the array that doInBackground() returns? The Java tutorial for SwingWorker suddenly returns numbers which isn't defined anywhere to be an array or anythin else.

So I guess I have to make process() call (my) report(), which appends new info to the output window (text area). I assume that once doInBackground() fills the array of chunks, it will be easy to process them.

But where do I put get()? The Java tutorial for SwingWorker sort of suggests that get() isn't necessary, since the example writes to a text area and get() is merely used with System.out to display the same info on the console.

(EDIT) Oh yeah... What do I publish()? I guess I publish inside report().

But I'm posting anyway since I THINK the question and/or answer COULD be a valuable find for someone asking the next question about SwingWorker.

(EDIT) A big problem I think I face is that walkFileTree more or less "is" a loop, repeatedly calling visitFile() behind the scenes, ending when the tree ends or when the return value in visitFile() is set to TERMINATE. So do I just stick visitFile() in doInBackground() since it's more or less already in a loop? And then put publish() right after it?

But then how do I return an array?

Ug.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
DSlomer64
  • 4,234
  • 4
  • 53
  • 88

1 Answers1

3

So I'm looking for something to implement. My notes tell me "Because SwingWorker implements Runnable, a SwingWorker can be submitted to an Executor for execution" so I think I'm heading there next unless somebody stops me! (I've never used executors before.)

After I figure out how in involve SwingWorker, I assume I should do the following, probably in jbSearch...() in place of the 3 lines shown (just above):

TASK.execute();

Yes, SwingWorker#execute is the typical way to start a SwingWorker

I guess I have to make doInBackground() call visitFile(), which is what is applied to all the files in the walk. Is it MY responsibility to fill the array that doInBackground() returns? The Java tutorial for SwingWorker suddenly returns numbers which isn't defined anywhere to be an array or anythin else.

Anything you want done in the background should be called from this method.

Yes, you need to generate the result yourself. The actual value can be defined anywhere, but I personally define a local variable within the context of the doInBackground method

So I guess I have to make process() call (my) report(), which appends new info to the output window (text area). I assume that once doInBackground() fills the array of chunks, it will be easy to process them.

In order for values to be processed, you need to first publish them. When these values are passed to process will depend on how intensive your background process is.

Overriding done and calling get will also allow you to access what was returned from doInBackground within the context of the EDT

But where do I put get()? The Java tutorial for SwingWorker sort of suggests that get() isn't necessary, since the example writes to a text area and get() is merely used with System.out to display the same info on the console. If I don't need to call get(), maybe I'm closer to a solution that I thought when I started this.

This will depend. Do you care about the result? If you do, I tend to call it within the done method, because, generally, I want to use the values within the EDT.

The important thing to know about get is that it is blocking, that is, it will wait until doInBackground returns

For example

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • @Mad--Thanks for quick reply. (1) Should I use `class TASK extends SimpleFileVisitor implements Executor`? (2) Syntax is `public void execute(**Runnable command**)`; what's the argument? (3) Is `execute()` where I should put whatever is currently in the run() method for SimpleFileVisitor, which includes `walkFileTree`? (4) What goes inside `execute()`? Is it what I mentioned in (3)? – DSlomer64 Nov 16 '13 at 21:09
  • @Mad--I should maybe go back to drawing board since I have read nothing about `execute()` and `Executor`, so I don't know how `SwingWorker.execute()` gets linked to `TASK` nor how to even ask an intelligent question about it. I think I'm almost back to square 1. I thought I had an idea how to proceed; now I feel clueless. – DSlomer64 Nov 16 '13 at 21:14
  • Create an instance of SwingWorker and call execute. SwingWorker has its own executor and manages the posses itself – MadProgrammer Nov 16 '13 at 21:42
  • I asked a similar question [(link)](http://stackoverflow.com/questions/20060366/swingworker-with-filevisitor-class-and-walkfiletree-which-iterates-internally) and posted my solution, based on @Mad's encouragement. The solution didn't involve SwingWorker, so much of this thread doesn't much matter. – DSlomer64 Dec 08 '13 at 02:49