Правильно обрабатывать перезагрузку и перезапуск из AppletViewer - PullRequest
12 голосов
/ 10 сентября 2011

Когда мой апплет запускается в первый раз из чистой среды, все работает так, как я ожидаю.Я породил два потока, один для общей обработки и один для графики.Я делаю все вызовы манипулирования GUI из потока диспетчеризации событий.Старт / Стоп обрабатывается корректно из окна просмотра апплетов, но перезапуск / перезагрузка - нетУ меня есть Canvas с именем drawCanvas как единственный компонент на панели содержимого моего апплета, и я использую двойную буферизацию для рисования на нем.

Я наблюдаю проблему здесь:

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 */
                }
    /* ... */

Где 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);
}

Также вот соответствующий код в 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 */

В первый раз все отлично работает.Когда я делаю перезапуск с appletviewer, сначала вызывается stop(), который заставляет все мои потоки переходить в состояния ожидания.Затем вызывается destroy(), который снова пробуждает все мои потоки и позволяет им завершиться, а также do и invokeAndWait() в EDT, чтобы очистить мои виджеты и выполнить setVisible (false).Таким образом, после того как destroy завершает appletviewer вызовы init / start снова, и процесс повторяется точно так же, как и раньше, за исключением того, что он завершается с ошибкой в ​​start() в области, которую я отметил выше.

Что-то, что я заметил, что не имело для меня большого смысла, было то, что, если я клонировал апплет, используя appletviewer, а затем перезагрузил клон, все будет работать, как ожидалось, когда я попытался перезапустить или перезагрузить клон.в первый раз, но произойдет сбой с исключением во второй раз.

Что-то еще, что я заметил при попытке отладить эту проблему, это то, что appletviewer и браузер действуют полностью по-разному как хосты для моего апплета;они даже не звонят init() и start() при одинаковых условиях.Кроме того, перезапуск и перезагрузка кажутся не более чем вызовом stop() -> destroy() -> init() -> start(), но с небольшими изменениями в среде выполнения.

Так что мой вопросв чем смысл операций перезапуска и перезагрузки (т. е. когда они используются) и является ли проблемой то, что мой апплет завершается ошибкой в ​​средстве просмотра апплетов, когда они происходят?

1 Ответ

6 голосов
/ 31 января 2012

Хороший вопрос. Чтобы ответить на этот вопрос, нам нужно сначала понять блоки кода Java. у нас есть анонимные статические блоки перед исполнителем, который будет выполнен.

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);
    }
}

призывание:

 <applet code="AppletTest.class" height=300 width=300></applet>

при запуске этого класса с помощью appletviewer вы можете заметить разницу. Апплет, запущенный в первый раз, вы получите

    I m static block
    I m Anonymous block
    I m constructor
    init
    start

при перезапуске апплета -

stop
destory
init
start

и при перезагрузке апплета

stop
destory
I m Anonymous block
I m constructor
init
start

для вашего второго вопроса, апплет не гарантирует одинаковый вывод на разных ОС, сетевых и аппаратных компонентах.

...