Код проверки Swing в потоке отправки событий во время выполнения - PullRequest
10 голосов
/ 10 июня 2010

Существуют ли библиотеки, которые кодируют инструмент для проверки того, что методы, вызываемые на компонентах Swing, вызываются в потоке диспетчеризации событий?Вероятно, было бы не слишком сложно написать некоторый базовый код для этого, но я уверен, что есть крайние случаи и тому подобное, которые другие люди обрабатывали.Я ищу это во время выполнения, а не для модульных тестов.

Ответы [ 4 ]

11 голосов
/ 10 июня 2010

Фреймворк FEST имеет инструмент для определения использования Swing вне EDT.Это в основном RepaintManager, который вы устанавливаете.Каркас ориентирован на тестирование, но RepaintManager можно использовать во время развертывания.

В качестве альтернативы,чтобы проверить все методы, такие как методы получения и установки, для доступа только к EDT, вы можете использовать AspectJ и ткачество во время загрузки, чтобы добавить рекомендацию SwingUtilities.isDisaptchThread () для каждого метода в ваших компонентах Swing (и компонентах JDK Swing).

@Aspect
public class EDTCheck {

    @Pointcut("call (* javax.swing..*+.*(..)) || " +
              "call (javax.swing..*+.new(..))")
    public void swingMethods() {}

    @Pointcut("call (* com.mystuff.swing..*+.*(..)) || " +
              "call (com.mystuff.swing..*+.new(..))")
    public void mySwingMethods() {}


    @Pointcut("call (* javax.swing..*+.add*Listener(..)) || " +
              "call (* javax.swing..*+.remove*Listener(..)) || " +
              "call (void javax.swing.JComponent+.setText(java.lang.String))")
    public void safeMethods() {}

    @Before("(swingMethods() || mySwingMethods()) && !safeMethods()")
    public void checkCallingThread(JoinPoint.StaticPart thisJoinPointStatic) {
        if(!SwingUtilities.isDispatchThread()) {
            System.out.println(
                    "Swing single thread rule violation: " 
                    + thisJoinPointStatic);
            Thread.dumpStack();
            // or you might throw an unchecked exception
        }
    }

}

(Немного изменено из статьи - добавлен pointcut mySwingMethods и используется SwingUtiliites.isDispatchThread (). На практике это то же самое, что EventQueue.isDispatchThread (), но абстракция чище.)

2 голосов
/ 14 сентября 2012

Я столкнулся с простым и умным (хотя и не полностью пуленепробиваемым) методом Скотта Делапа в http://today.java.net/pub/a/today/2005/04/19/desktoplive.html.

Как указано в ответе FEST от mdma выше, можно использовать пользовательский RepaintManger, просто переопределив методы

addInvalidComponent(JComponent component) 

и

addDirtyRegion(JComponent component, int x, int y, int w, int h)

и используйте

SwingUtilities.isEventDispatchThread()

чтобы проверить, находимся ли мы на AWT, вы можете довольно легко интегрировать это в JUnit, добавив

org.JUnit.Assert.fail("AWT Thread Violation")

в вашей процедуре проверки.

Логика здесь в том, что большинство (но не все) операции Swing вызывают перерисовку, которая в конечном итоге вызывает эти методы в RepaintManager, чтобы мы могли их перехватить и выполнить нашу проверку.

Александр Поточкин имеет хороший обзор различных методов здесь: http://weblogs.java.net/blog/alexfromsun/archive/2006/02/debugging_swing.html

2 голосов
/ 10 июня 2010

С точки зрения кодирования четко отделить код EDT от кода не EDT.Избегайте SwingWorker, как чумы.

Чтобы подтвердить, что вы находитесь на EDT (введите ! для выключения), добавьте строку:

assert java.awt.EventQueue.isDispatchThread();

Вам понадобится -ea/ -enableassertions для этого нужно что-нибудь сделать.Тем не менее, он в основном работает как исполняемый комментарий.

1 голос
/ 10 июня 2010

Все, что вам нужно, это следующий код:

void method() {
    if (!SwingUtilities.isEventDispatchThread()) {
       SwingUtilities.invokeAndWait(new Runnable() { public void run() { method(); } );
       return;
    }

    // do method code here, guaranteed to be in EDT
}

Кроме того, использование Вещество в качестве LAF поможет вам понять, где материалы, связанные с Swing, не выполняются в EDT. У него есть проверки, чтобы убедиться, что все вещи Swing выполнены в правильном потоке, или это происходит с ошибкой за исключением.

...