Catch exceptions in javax.swing application

2019-02-17 11:05发布

问题:

I'm working with javax.swing to make an aplication which generates forms from XML Schema (using JAXFront library) and stores the data filled by the user them into XML documents.

I have put try-catch-finally blocks when I need it, but I have a little problem catching exceptions when the main thread ends (The AWT threads are still running).

I have two classes which do the main work and other classes which aren't important for the question:

  • Main class: It has the following structure. Initializes the application and runs the main frame

    public class Main { 
        public static void main(String[] args) {
            readArgs(); // An INI file with the app config
            Model model = initializeElements(args); // My model class
            try {
                MyFrame mfr = new MyFrame(title,model);
                mfr.visualize(); // Assembling view and setting visible
            } catch( Excepion e ) {
                doCleanUp();
                System.exit(-1);
            }
        }
    }
  • Frame Class: Generates the view and listen events

    public class MyFrame extends JFrame implements ActionListener,MenuListener { 
        // Some attributes
        // Other mthods without importance
        /**
         * Compose the elements, add listeners and set visible the frame
         */
        public void visualize() {
            generateFormPanel();
            setListeners();
            validate();
            setVisible(true);
        }
    
        public MyFrame(String title, Modele model) {
            super(title);
            createElementsUsing(model);
        }
    
        public void actionPerformed(ActionEvent e) {
            // Code to manage events
        }
    }

Well, the problem is the following: When the visualize function is exectuted from the main method, the view is generated and showed. At that moment is when I lose the control of the exceptions catching. Then my question is if there are some way to catch the possible RuntimeExceptions throwed after this point.

I hope you understand my English and can answer the question.

Thanks in advance.

回答1:

Simplest version is to set the default uncaught exception handler:

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    public void uncaughtException(Thread t, Throwable e) {
        // do something
    }
});

But that catches uncaught exceptions thrown in other parts of the program aswell.

You could however catch only runtime exceptions thrown off the swing event dispatching thread using a proxy (See this page for more information, copied code from there):

class EventQueueProxy extends EventQueue {

    protected void dispatchEvent(AWTEvent newEvent) {
        try {
            super.dispatchEvent(newEvent);
        } catch (Throwable t) {
            // do something more useful than: t.printStackTrace();
        }
    }
}

Now installing it like this:

Toolkit.getDefaultToolkit().getSystemEventQueue().push(new EventQueueProxy());


回答2:

After you have called visualize() the only thread running is the Swing/AWT event dispatch thread. If you want to catch any exceptions you will need to do so in any of your listener methods that are called on this thread e.g.

public void actionPerformed(ActionEvent e) {
  try {
    // Some code here
  } catch(RuntimeException e) {
    // Handling code here
  }
}

To prevent boilerplate you can have this code in a super class.

Note that you can also set a default uncaught exception handler if you want to catch anything not already dealt with by the Swing/AWT thread.

Note also that in general it is best practice to not catch subclasses of RuntimeException if you can avoid it.



回答3:

Try adding:

setDefaultCloseOperation(EXIT_ON_CLOSE);

to MyFrame constructor. Not sure though, but worth trying.