Search code examples
javaappletawtkeylistenerrunnable

Button not displaying in applet


The following is the condensed code of my applet game:

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

public class Game extends Applet implements KeyListener, Runnable {
    Button options = new Button("Options");
    Thread thread = new Thread(this);

    public void init() {
        addKeyListener(this);
        thread.start();
    }

    public void paint(Graphics graphics) {
        // draw stuff
    }

    public void run() {
        try {
            while (true) {
                thread.sleep(40);
                repaint();
            }
        } catch (InterruptedException exception) {}
    }

    public void keyPressed(KeyEvent keyEvent) {
        switch (keyEvent.getKeyCode()) {
        case KeyEvent.VK_ESCAPE:
            // pause game
            add(options);
        }
    }

    public void keyReleased(KeyEvent keyEvent) {}
    public void keyTyped(KeyEvent keyEvent) {}
}

My game runs as it's expected to. However when the user presses Esc I want to pause the game and display an options button.

The problem is that when I press Esc it pauses the game as expected. However it doesn't display the button on the screen. I've tried to search for a solution to no avail. What exactly is happening?


Solution

  • Works perfectly fine for me...

    public class TestApplet02 extends Applet implements KeyListener, Runnable {
    
        Button options = new Button("Options");
        Thread thread = new Thread(this);
        int y = 0;
    
        public void init() {
            thread.start();
        }
    
        @Override
        public void start() {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    setLayout(new BorderLayout());
                    addKeyListener(TestApplet02.this);
                }
            });
        }
    
        public void paint(Graphics graphics) {
            super.paint(graphics);
            Graphics2D g2d = (Graphics2D) graphics;
            y++;
            if (y > getHeight()) {
                y = 0;
            }
            g2d.drawLine(0, y, getWidth(), y);
        }
    
        public void run() {
            try {
                while (true) {
                    thread.sleep(40);
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            repaint();
                        }
                    });
                }
            } catch (InterruptedException exception) {
            }
        }
    
        public void keyPressed(KeyEvent keyEvent) {
            switch (keyEvent.getKeyCode()) {
                case KeyEvent.VK_ESCAPE:
                    // pause game
                    add(options);
                    invalidate();
                    revalidate();
            }
        }
    
        public void keyReleased(KeyEvent keyEvent) {
        }
    
        public void keyTyped(KeyEvent keyEvent) {
        }
    }
    

    From the link TrashGod provided...

    In an applet, the GUI-creation task must be launched from the init method using invokeAndWait; otherwise, init may return before the GUI is created, which may cause problems for a web browser launching an applet. In any other kind of program, scheduling the GUI-creation task is usually the last thing the initial thread does, so it doesn't matter whether it uses invokeLater or invokeAndWait.

    UPDATED

    The major issues I had were:

    In you're escape key handler, if direction is 0, the pause option will never activate...

    case KeyEvent.VK_ESCAPE:
        direction = -direction;
    
        if (direction < 0) {
            add(options);
        } else {
            remove(options);
        }
    

    The other thing I had to was call revalidate...

    invalidate();
    revalidate();
    repaint();