Существуют ли какие-либо библиотеки, которые используют код для проверки того, что методы, вызываемые компонентами Swing, вызываются в потоке отправки событий? Вероятно, было бы не слишком сложно написать базовый код для этого, но я уверен, что есть крайние случаи и еще много чего, с чем работали другие люди. Я ищу это во время выполнения, а не для модульных тестов.
Код проверки Swing в потоке отправки событий во время выполнения
Ответы (4)
В структуре FEST есть инструмент для обнаружения использования Swing вне EDT. По сути, вы устанавливаете RepaintManager. Фреймворк ориентирован на тестирование, но RepaintManager можно использовать во время развертывания.
В качестве альтернативы, чтобы проверить все методы, такие как геттеры и сеттеры, для доступа только к EDT, вы можете использовать AspectJ и weaving во время загрузки, чтобы добавить совет 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 (), но абстракция более чистая.)
Я наткнулся на простой и умный (хотя и не совсем пуленепробиваемый) метод Скотта Делапа по адресу 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
RepaintManager.setCurrentManager(new MyRepaintManager());
- person Joshua Goldberg; 03.09.2014
С точки зрения кодирования, четко отделите код EDT от кода, не относящегося к EDT. Избегайте SwingWorker
, как чумы.
Чтобы подтвердить, что вы находитесь в EDT (вставьте !
для выключения), добавьте строку:
assert java.awt.EventQueue.isDispatchThread();
Для этого вам понадобится _4 _ / _ 5_. Однако в основном он работает как исполняемый комментарий.
invokeLater
.
- person Tom Hawtin - tackline; 10.06.2010
Все, что вам нужно, это следующий код:
void method() {
if (!SwingUtilities.isEventDispatchThread()) {
SwingUtilities.invokeAndWait(new Runnable() { public void run() { method(); } );
return;
}
// do method code here, guaranteed to be in EDT
}
Кроме того, использование Substance в качестве вашего LAF поможет вам определить, где вещи, связанные с Swing, не исполняется на EDT. У него есть проверки, чтобы убедиться, что все Swing-файлы выполняются в правильном потоке, в противном случае он не работает с исключением.
invokeLater
. Конечно, избегайте invokeAndWait
, если вам не нравятся тупиковые ситуации. assert java.awt.EventQueue.isDispatchThread();
- сделано.
- person Tom Hawtin - tackline; 10.06.2010