Search code examples
javamultithreadingswingfilevisitor

Program displays filenames in a JTextArea as it walks the directory tree but I don't know how to stop it via a keypress


There are two windows: a GUI for user input and Output window for list of filenames found. Execution must be user-stoppable via a keypress and must leave both windows open because the program processes subdirectories, so it can run a long time, possibly stepping thru 100_000 files, either producing tons of output or none at all, depending on how user's filename pattern matches files encountered in the selected starting node.

Here's my question:

How do I look for a keypress (e.g., ESC or CTRL-C) to allow user to terminate? (Clicking red X isn't an option since that closes windows; user needs to see what's been found before termination. Doing so does not close either window anyway since all buttons are disabled once tree walk begins.)

I've tried putting keyListeners in several places, but once the "Start" button is clicked, all the swing components are disabled.

This seems like such a common situation that I'm surprised I can't find any textbook, thread, or Google info that directly answers the question. So I'm afraid it's not gonna be at all easy. That would be no surprise. I may have found a clue here but I can't get it to compile and the link contained there doesn't lead to that code snippet.

The search begins when the Search button is clicked:

  private void jbSearchActionPerformed(ActionEvent evt) { 
     SearchyGUI.doIt();
  }                                        

The doIt() method walks the directory tree by an extension of SimplefileVisitor:

  public class OverriddenFileVisitor extends SimpleFileVisitor<Path> {
    ...
  }

  public static void doIt(){
    try {
      visitor = new OverriddenFileVisitor();
      info.setVisible(true);
      Files.walkFileTree(SearchyGUI.p , visitor);
    }
    catch (Exception e) {    }
  }   
}

Output is written to jTextArea1 via the report() method:

  public static void report(String s){
    Output.jTextArea1.append(s + "\n");
  }

This is done primarily in the visitFile() method of SimpleFileVisitor:

 public FileVisitResult visitFile(Path f, BasicFileAttributes a) throws IOException {
    report(foundkt + "--" + f.getFileName().toString());
    return FileVisitResult.CONTINUE;
  }

Here's the main class:

public class SearchyGUI {

  static Output info;
  static Path p ;
  static FileVisitor visitor ;
  static GUI gui 

public static void main(String args[]) {
    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();
      }
    });
  }

Solution

  • The problem is you are hogging the GUI thread, so the GUI thread can't process any events originating from the user.

    You need to create a new Thread and do the work in there. Then, to display output from that thread, you can use SwingUtilities.invokeLater or something like that.