2010-05-06 75 views
1

首先,这里有一些代码段:问题与Java join()方法

public void startThread() { 
    this.animationThread = new Thread(this); 
    this.animationThread.start(); 
    try { 
     this.animationThread.join(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 

@Override 
public void run() {  
    pirateMainAnimation.animate(); 
} 

public void animate() { 
    for (int j = 0; j < 9; j++) { 
     try { 
      Thread.sleep(250); 
     } catch (InterruptedException e) { 
      break; 
     } 
     PirateAnimationPanel.getInstance().setCurrent(j); 
     PirateAnimationPanel.getInstance().repaint(); 
    } 
} 

我试图动画一些图片。问题是我想要主线程等待动画线程完成并继续。我搜索了一下,读了一下,然后决定使用join()方法。它完美地等待线程完成,但我没有正确动画。 repaint()方法被调用2次而不是9次。我想也许问题是因为我使用了单身人士。这是单例实现。

import java.awt.Graphics; 
import java.awt.MediaTracker; 

import javax.swing.JPanel; 

import uk.ac.aber.dcs.piratehangman.animation.PirateMainAnimation; 
import uk.ac.aber.dcs.piratehangman.utilityclasses.AnimationThread; 

@SuppressWarnings("serial") 
public class PirateAnimationPanel extends JPanel { 
    private int current; 
    private MediaTracker mTracker; 
    private PirateMainAnimation pirateMainAnimation; 
    private AnimationThread animationThread; 

    private PirateAnimationPanel() { 
     this.current = 0; 
     this.pirateMainAnimation = new PirateMainAnimation(); 
     mTracker = new MediaTracker(this); 
     this.animationThread = new AnimationThread(); 
     setMediaTracker(); 
     repaint(); 
    } 

    private void setMediaTracker() { 
     for (int i = 0; i < 9; i++) { 
      mTracker.addImage(
        this.pirateMainAnimation.getImagesForAnimation()[i], 
        this.pirateMainAnimation.getImagesForAnimationID()[i]); 
      try { 
       mTracker.waitForID(this.pirateMainAnimation 
         .getImagesForAnimationID()[i]); 
      } catch (InterruptedException e) { 
       System.out.println("Error loading image: " + i); 
      } 
     } 
    } 

    public void playAnimation() { 
     this.animationThread.startThread(); 
    } 

    public void paintComponent(Graphics g) { 
     super.paintComponents(g); 
     System.out.println("called"); 
     g.drawImage(this.pirateMainAnimation.getImagesForAnimation()[current], 
       0, 0, this); 
    } 

    private static class PirateAnimationPanelHolder { 
     private static final PirateAnimationPanel pirateAnimationPanel = 
      new PirateAnimationPanel(); 
    }; 

    public static PirateAnimationPanel getInstance() { 
     return PirateAnimationPanelHolder.pirateAnimationPanel; 
    } 

    public void setCurrent(int current) { 
     this.current = current; 
    } 

    public int getCurrent() { 
     return current; 
    } 
} 
+0

考虑发布的代码为你的问题的一部分,而不是托管在别的地方,如果你需要帮助让它正确格式化,只是这样说,我会很乐意为你编辑代码。 – 2010-05-06 03:38:41

+0

我认为在这里发布只会妨碍问题的解决。无论如何,如果你对我这样做很好,我会很高兴,因为我从来没有在这里发布代码。谢谢 :)。 – gmunk 2010-05-06 03:41:19

+0

当然,要在SO上格式化代码,只需在每行前面缩进四个空格即可。我将在代码中进行编辑,如果您之后点击编辑,则可以看到我的意思。并且欢迎来到StackOverflow btw :)另外,我注意到你在你的文本中使用了TAB,这也必须被编辑出来并用SO上的空格替换。无论如何,代码编辑英寸,并回答您的评论中隐含的问题,不,这里的代码将不会妨碍问题的方式,只要它的大小,代码将脱颖而出,因为你可以看到,所以它是很容易看到什么是代码和什么是问题。 – 2010-05-06 03:42:03

回答

2

我认为你的意思是paintComponent()方法只被调用两次。此外,我认为如果您将组件填充到背景颜色,您应该能够移除对super.paintComponents()的调用。

repaint()方法只会将该组件标记为脏,并请求在下一个paint上重新渲染。

我会期望Swing线程能够在250ms内重绘,但我不确定还有哪些其他工作正在完成/呈现。您可能想在动画之前调用MediaTracker.waitForAll()。

虽然静态单例没有增加太多,但我不认为这是造成问题(在这种情况下)。

更新: 所以问题是,join()是在Swing事件线程,阻止组件重绘。我提出了一个调用,比如下面显示的“最后的动画完成后,新的游戏对话框:

SwingUtilities.invokeLater(new Runnable() { 
    public void run() { showDialog(); } 
}) 
+0

感谢您的回复,有趣的是,当从代码中删除对join()方法的调用时。它工作正常。很奇怪,我会尝试你的想法。 – gmunk 2010-05-06 03:46:51

+0

因此,在最后一次调用repaint()之后,“动画线程”可以在渲染完成之前退出/停止。你是否允许应用程序继续和没有连接? 什么触发playAnimation()是从Swing线程(鼠标/键盘事件还是Applet)调用的? 编辑:缺字 – 2010-05-06 03:54:51

+0

playAnimation()虽然被JButton调用,但它依赖于某个条件。逻辑大致如下。用户在文本字段中输入一个单词,并在动画播放的猜测错误时按下按钮。这种错误的猜测减少了用户的生活,他再次尝试,如果再次错误,动画再次播放,但是这次在完成后弹出框出现询问用户是否想要新游戏。使用代码中的join()方法,但动画仅渲染第一张和最后一张图片。使用join()方法渲染完美,但弹出框 – gmunk 2010-05-06 04:01:31

1

‘请注意,事件被发布到EventQueue可以被合并,’这也许可以解释的差异另外,可以肯定。打造你的GUI上event dispatch thread进行更详细的讨论,请参阅A More Complex Image Icon Example

附录:。Improving Perceived Performance When Loading Image Icons有一个很好的SwingWorker的例子,可以简化卸载

+0

我正在使用事件分派线程。谢谢你的回复,我会检查链接:)。 – gmunk 2010-05-06 04:06:02

+0

非常好。 @Rob Moore对于不阻止美国东部时间是正确的。我已经添加了上面的“SwingWorker”示例的链接。 – trashgod 2010-05-06 15:58:38