Slick TextField not working

2019-05-06 16:35发布

问题:

I have a problem when using Slick2D's TextField.

When using Slick's 'BasicGame' the TextField works fine - I am able to click on it, type words, and System.out.println the text fields contents.

However, when using the same code on a 'BasicGameState', the TextField is un-clickable and doesn't respond to any input.

So: Working code:

package Help;
import java.awt.Font;
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.UnicodeFont;
import org.newdawn.slick.font.effects.ColorEffect;
import org.newdawn.slick.gui.AbstractComponent;
import org.newdawn.slick.gui.ComponentListener;
import org.newdawn.slick.gui.TextField;

public class TextFieldWorking extends BasicGame{
    private TextField text1;
    private UnicodeFont font = getNewFont("Arial" , 16);


    public TextFieldWorking() {
        super("Test");
    }
    @Override
    public void init(GameContainer container) throws SlickException {
        font.loadGlyphs();
        text1 = new TextField(container, font, 50,50,100,25);
    }
    @Override
    public void update(GameContainer gc, int delta) throws SlickException {
        System.out.println(text1.getText());
    }
    @Override
    public void render(GameContainer gc, Graphics g) throws SlickException {
        text1.render(gc, g);
    }
    public UnicodeFont getNewFont(String fontName , int fontSize){
        UnicodeFont returnFont = new UnicodeFont(new Font(fontName , Font.PLAIN , fontSize));
        returnFont.addAsciiGlyphs();
        returnFont.getEffects().add(new ColorEffect(java.awt.Color.white));
        return (returnFont);
    }
    public static void main(String[] args) throws SlickException  {
        TextFieldWorking g = new TextFieldWorking();
        AppGameContainer gc = new AppGameContainer(g);
        gc.setDisplayMode(500, 500, false);
        gc.start();
    }
}

Non-Working code:

package Help;
import java.awt.Font;
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.UnicodeFont;
import org.newdawn.slick.font.effects.ColorEffect;
import org.newdawn.slick.gui.AbstractComponent;
import org.newdawn.slick.gui.ComponentListener;
import org.newdawn.slick.gui.TextField;

import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;


public class TextFieldTest extends BasicGameState{

    int WindowWidth, WindowHeight;  
    TextField text1;
    private UnicodeFont font = getNewFont("Arial" , 16);
    private int stateId = 0;

    public TextFieldTest(int State) {
        this.stateId = State;
    }

    public void init(GameContainer gc, StateBasedGame sbg) throws SlickException{

        WindowWidth = gc.getWidth();
        WindowHeight = gc.getHeight();
        font.loadGlyphs();
        text1 = new TextField(gc, font, 50,50,100,25);
    }

    public void render(GameContainer gc, StateBasedGame sbg, Graphics g) throws SlickException{
        text1.render(gc, g);
    }

    public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException{
        System.out.println(text1.getText());
    }

    public UnicodeFont getNewFont(String fontName , int fontSize){
        UnicodeFont returnFont = new UnicodeFont(new Font(fontName , Font.PLAIN , fontSize));
        returnFont.addAsciiGlyphs();
        returnFont.getEffects().add(new ColorEffect(java.awt.Color.white));
        return (returnFont);
    }

    public int getID(){
        return this.stateId; //Returns the Id of this state (menu is 0)
    }
}

For convenience:

This goes with the BasicGameState - It's how Slick2D works - you can just copy - paste code now :P

package Help;
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.StateBasedGame;

public class Game extends StateBasedGame{

    public static final String gamename = "Problem!";
    public static final int TextFieldTestNum = 1;

    public Game(String gamename){
        super(gamename); 
        this.addState(new TextFieldTest(TextFieldTestNum));

    }
    public void initStatesList(GameContainer gc) throws SlickException{
        this.getState(TextFieldTestNum).init(gc, this);
        this.enterState(TextFieldTestNum); //The First state to enter
    }

    @Override
    public boolean closeRequested(){
        System.exit(0);
        return false;
    }

    public static void main(String[] args) {
        AppGameContainer appgc;
        try{
            Game g = new Game(gamename);
            appgc = new AppGameContainer(g);
            appgc.setDisplayMode(500, 500, false);
            appgc.start();
        }catch(SlickException e){
            e.printStackTrace();
        }
    }
}

Any ideas appreciated!

回答1:

Your problem is how you are going about StateBasedGames in slick. If you refer to my wiki entry here: http://slick.ninjacave.com/wiki/index.php?title=Game_States

You will notice that in the initStatesList() method, I only use this.addState(new StateName()). This is because of what addState() method does. It calls the init method for you, so there is no need to do getState() or enterState() in the top level Application class (Game.java in your case).

To summarize how to fix your problem, remove everything in your initStatesList() method, then move this.addState(new TextFieldTest(TextFieldTestNum)); from your main constructor to your initStatesList() method.

Once I corrected that in your program, it ran just fine for me.