Search code examples
javaappletawt

Java AWT - repaint() method thread scheduling


What I am looking to do is have the user to be able to change perspectives from a KeyListener. If the user hits the specified key, than the perspective should change. Any ideas?

Even if I override the methods they still do not work. I have also tried KeyAdapter

package com.development.gameOne.environment.component;

import java.applet.Applet;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;

import com.development.gameOne.environment.applet.drawing.Perspective;
import com.development.gameOne.environment.applet.perspectives.p1.FirstPerspective;
import com.development.gameOne.environment.applet.perspectives.p2.SecondPerspective;

public class Component extends Applet implements KeyListener {

    private static final long serialVersionUID = 1L;
    private Dimension size = new Dimension(1280, 720);

    private ArrayList<Perspective> perspectives = new ArrayList<Perspective>();
    private boolean running = true;
    private boolean switchPerspective = false;

    public Component() {
        setPreferredSize(size);
        loadPerspectives();
        addKeyListener(this);
        setFocusable(true);
        setVisible(true);
        start();
    }

    private void loadPerspectives() {
        perspectives.add(new FirstPerspective());
        perspectives.add(new SecondPerspective());
    }

    public static void main(String[] args) {
        new Component();
    }

    @Override
    public void paint(Graphics g) {
        while (running) {
            for (Perspective p : perspectives) {
                System.out.println(p.getPerspective());
                while (!switchPerspective) {
                    System.out.println("Rendering");
                    p.start(g);
                    sleep(100);
                }
                switchPerspective = false;
            }
            sleep(10);
        }
    }

    public static void sleep(int renderSpeed) {
        try {
            Thread.sleep(renderSpeed);
        }
        catch (Exception e) {}
    }

    public void keyPressed(KeyEvent e) {
        switch(e.getKeyCode()){
        case KeyEvent.VK_SHIFT:
            System.out.println("KeyPressed");
            switchPerspective = true;
            break;
        }
    }



    public void keyTyped(KeyEvent e) { }

    public void keyReleased(KeyEvent e) {}

}

The program runs, but doesn't switch perspectives. I cannot seem to get the KeyListener to work at all. I really have no idea what to do.


Solution

  • I don't think the issue is with your KeyListener, but is with your paint process

    @Override
    public void paint(Graphics g) {
        while (running) {
            for (Perspective p : perspectives) {
                System.out.println(p.getPerspective());
                while (!switchPerspective) {
                    System.out.println("Rendering");
                    p.start(g);
                    sleep(100);
                }
                switchPerspective = false;
            }
            sleep(10);
        }
    }
    

    This will block the Event Dispatching Thread, preventing it from ever been able to process new events coming into the system

    Take a look at Painting in AWT and Swing for details about how painting works in AWT.

    The (simple) solution, in this case, would be to provide a other Thread which handles the timing between updates and simple call repaint when you want the UI updated.

    A better solution would be take take advantage of the a BufferStrategy instead. It still require a Thread, but stops you from breaking the painting chain.

    As a side note. AWT Applets are woefully out-of-date and were replaced by JApplet before 2000. Having said that, I would recommend against using applets at all, as they have enough problems which only increases the difficulty of starting development and focus on something like a JPanel added to an instance of a JFrame instead.

    Take a look at Performing Custom Painting and Creating a GUI With JFC/Swing

    I'd also drop the use of KeyListener as soon as you can in favour of Swing's Key bindings API. See How to Use Key Bindings for more details

    I'd also avoid calling your applet Component, there already is a class called Component and this is just going to confuse matters...

    And applets, definitely, should not have a main method. They are expected to be loaded by the browser directly and have a different, defined, life cycle.