代码之家  ›  专栏  ›  技术社区  ›  Jeff Storey

运行时事件调度线程上的Swing验证代码

  •  10
  • Jeff Storey  · 技术社区  · 14 年前

    是否有库插入代码以验证在Swing组件上调用的方法是否在事件调度线程上调用?写一些基本的代码来实现这一点可能不会太难,但我确信有一些边缘案例和其他人处理过的其他事情。我在运行时寻找这个,而不是单元测试。

    4 回复  |  直到 9 年前
        1
  •  11
  •   Gili    13 年前

    这个 FEST 框架有一个工具来检测EDT之外的Swing使用情况。它基本上是一个你安装的重绘管理器。该框架面向测试,但repaitmanager可以在部署时使用。

    或者,要检查所有方法(如getter和setter),以便仅在EDT上访问,可以使用AspectJ和加载时编织向swing组件(和JDK swing组件)上的每个方法添加SwingUtilities.isDisaptchThread()建议

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

        2
  •  2
  •   dassimon    12 年前

    http://today.java.net/pub/a/today/2005/04/19/desktoplive.html .

    正如上面mdma在FEST答案中所暗示的,可以使用定制的repaintmanager,只需重写这些方法

    addInvalidComponent(JComponent component) 
    

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

    使用

    SwingUtilities.isEventDispatchThread()
    

    为了检查我们是否使用AWT,您可以通过添加

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

    这里的逻辑是,大多数(但不是所有)Swing操作都会导致重绘,而重绘最终会在repaitmanager中调用这些方法,这样我们就可以捕获这些方法并进行检查。

    Alexander Potochkin在这里总结了各种方法: http://weblogs.java.net/blog/alexfromsun/archive/2006/02/debugging_swing.html

        3
  •  2
  •   Robin    9 年前

    从编码的角度,明确区分EDT代码和非EDT代码。避免 SwingWorker 就像瘟疫一样。

    断言你在EDT(插入 ! 对于off),添加以下行:

    assert java.awt.EventQueue.isDispatchThread();
    

    -ea / -enableassertions

        4
  •  1
  •   Chris Dennett    14 年前

    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将帮助你找出在EDT上没有执行Swing相关的东西的地方。它有适当的检查,以确保任何Swing操作都是在正确的线程上完成的,否则会出现异常而失败。