Перехватывать исключения в приложении javax.swing

Я работаю с javax.swing над созданием приложения, которое генерирует формы из схемы XML (используя библиотеку JAXFront) и сохраняет данные, заполненные пользователем, в документы XML.

Я помещал блоки try-catch-finally, когда мне это нужно, но у меня есть небольшая проблема с перехватом исключений, когда основной поток заканчивается (потоки AWT все еще работают).

У меня есть два класса, которые выполняют основную работу, и другие классы, которые не важны для вопроса:

  • Основной класс: имеет следующую структуру. Инициализирует приложение и запускает основной фрейм

    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);
            }
        }
    }
  • Класс фрейма: создает события просмотра и прослушивания.

    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
        }
    }

Ну, проблема в следующем: когда функция визуализации выполняется из основного метода, представление генерируется и отображается. В этот момент я теряю контроль над перехватом исключений. Тогда мой вопрос заключается в том, есть ли способ поймать возможные исключения RuntimeException, выброшенные после этой точки.

Надеюсь, вы понимаете мой английский и сможете ответить на вопрос.

Заранее спасибо.


person Charliemops    schedule 26.07.2011    source источник


Ответы (3)


Самая простая версия - установить обработчик необработанных исключений по умолчанию:

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

Но это ловит неперехваченные исключения, генерируемые и в других частях программы.

Однако вы можете перехватывать только исключения времени выполнения, выбрасываемые из потока диспетчеризации событий с помощью прокси-сервера (см. swing/" rel="noreferrer">эта страница для получения дополнительной информации, код скопирован оттуда):

class EventQueueProxy extends EventQueue {

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

Теперь устанавливаем так:

Toolkit.getDefaultToolkit().getSystemEventQueue().push(new EventQueueProxy());
person dacwe    schedule 26.07.2011
comment
Большое спасибо. Ваше первое решение решает мою проблему. Я не могу дать вам голос, но возьмите его! - person Charliemops; 26.07.2011

После того, как вы вызвали visualize(), единственным запущенным потоком является поток диспетчеризации событий Swing/AWT. Если вы хотите поймать какие-либо исключения, вам нужно будет сделать это в любом из ваших методов прослушивателя, которые вызываются в этом потоке, например.

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

Чтобы предотвратить шаблон, вы можете иметь этот код в суперклассе.

Обратите внимание, что вы также можете установить обработчик необработанных исключений по умолчанию, если вы хотите перехватить что-то, с чем еще не обработался поток Swing/AWT.

Также обратите внимание, что в целом рекомендуется не перехватывать подклассы RuntimeException, если вы можете этого избежать.

person Bringer128    schedule 26.07.2011

Попробуйте добавить:

setDefaultCloseOperation(EXIT_ON_CLOSE);

в конструктор MyFrame. Хотя не уверен, но попробовать стоит.

person LeleDumbo    schedule 26.07.2011
comment
Чтобы контролировать события выхода, у меня есть setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); и addWindowListener(new WindowAdapter(){...});, которые выполняют очистку. - person Charliemops; 26.07.2011