正确处理重新加载并从AppletViewer重新启动

Max*_*iso 12 java applet swing multithreading awt

当我的applet第一次从干净的环境启动时,事情按照我期望的方式工作.我产生了两个线程,一个用于通用处理,一个用于图形.我从事件调度线程执行所有GUI操作调用.从appletviewer正确处理启动/停止,但不重启/重新加载.我drawCanvas在Applet的内容窗格中将Canvas称为唯一的Component,我使用双缓冲来绘制它.

我在这里观察问题:

public void start() {   
    /* ... some stuff  */
    executeOnEDTAndWait( 
        new Thread() {
            @Override 
            public void run() {
                /* ... more stuff ... */
                setupDrawCanvas();

                if( drawCanvas.isDisplayable() ) {
                    drawCanvas.createBufferStrategy(2); 
                    /* ... some more stuff */
                } else {
                    /* This is where it runs into difficulties */
                }
    /* ... */
Run Code Online (Sandbox Code Playgroud)

在哪里setupDrawCanvas定义如下:

private void setupDrawCanvas() {
    setVisible(false);
    setIgnoreRepaint(true);

    getContentPane().removeAll();

    drawCanvas = new Canvas();

    drawCanvas.setName("drawCanvas");
    drawCanvas.setSize(
    newDrawCanvasDimension.width, 
    newDrawCanvasDimension.height);
    drawCanvas.setIgnoreRepaint(true);

    getContentPane().add(drawCanvas);

    getContentPane().setVisible(true);
    drawCanvas.setVisible(true);
    setVisible(true);
}
Run Code Online (Sandbox Code Playgroud)

另外,这是相关的代码 destroy()

public void destroy() {
    /* .. some stuff .. */

    /* dispose of drawCanvas */
    drawCanvas.setVisible(false);
    if( drawCanvas.getBufferStrategy() != null ) {
        drawCanvas.getBufferStrategy().dispose();
    }

    /* reset and disable the applet's GUI */
    setVisible(false);
    getContentPane().removeAll();
    removeAll();

    /* .. some more stuff */
Run Code Online (Sandbox Code Playgroud)

第一次通过,一切正常.当我从中重新启动时appletviewer,首先stop()调用它会导致我的所有线程进入等待状态.然后destroy()调用它再次唤醒我的所有线程并让它们退出,以及invokeAndWait()在EDT上执行以及清理我的小部件并执行setVisible(false).所以在destroy完成后appletviewer再次调用init/start并且该过程与之前完全重复,除非它在start()我上面提到的区域失败.

我注意到的对我来说没什么意义的是,如果我使用appletviewer然后重新加载克隆来克隆applet ,那么当我第一次尝试重新启动或重新加载克隆时,一切都会按预期工作,但是会因异常而崩溃第二次.

在尝试调试此问题时我注意到的其他一点是,appletviewer浏览器和我的applet的主机完全不同; 他们甚至没有打电话init(),也没有start()相同的条件.此外,重启和重新加载似乎只是对stop()- > destroy()- > init()- > 的调用,start()但对执行环境进行了微妙的修改.

所以我的问题是,重启和重新加载操作的意义是什么(即什么时候使用它们),这是appletview在发生时我的applet失败的问题吗?

und*_*ted 6

好问题.要回答这个问题,我们首先需要了解java代码块.我们在construtor之前有一个匿名的静态块,将被执行.

package com.test;

import java.applet.Applet;
import java.awt.*;

public class AppletTest extends Applet {
    {
        System.out.println("I m Anonymous block");
    }

    static {
        System.out.println("I m static block");
    }

    public AppletTest()
    {
        System.out.println("I m constructor");
    }

    public void init()
    {
        System.out.println("init");
    }

    public void start()
    {
        System.out.println("start");
    }

    public void stop()
    {
        System.out.println("stop");   
    }

    public void destroy()
    {
        System.out.println("destory");   
    }

    public void paint(Graphics g)
    {
        g.drawString("test Applet",10,10);
    }
}
Run Code Online (Sandbox Code Playgroud)

调用:

 <applet code="AppletTest.class" height=300 width=300></applet>
Run Code Online (Sandbox Code Playgroud)

使用appletviewer运行此类时,您可以注意到差异.Applet第一次运行你会得到

    I m static block
    I m Anonymous block
    I m constructor
    init
    start
Run Code Online (Sandbox Code Playgroud)

在做applet重启时 -

stop
destory
init
start
Run Code Online (Sandbox Code Playgroud)

并在applet重新加载

stop
destory
I m Anonymous block
I m constructor
init
start
Run Code Online (Sandbox Code Playgroud)

对于第二个问题,applet不保证在不同的操作系统,网络和硬件组件上输出相同的输出.