1

I'm in the process of attempting to simulate a Gameboy game in Java. I'm trying to print letters to a textbox every half of a second or so, but when I run the code, the box is drawn correctly, but there's no text in it.

Textbox:

package components;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.Timer;
import java.util.TimerTask;

public class Textbox extends Entity { //Only create one instance
private static String[] lines;
private static final int x = 1;
private static final int y = 97;
private Graphics2D graphics2D;
int lineNo = 0; //Used to count the line number when printing
int charNo = 0; //Used to count the character number when printing
int cx; //Used for the coordinates of each character printed
int cy; //Used for the coordinates of each character printed
boolean timerInitialized = false; //Used to indicate end of line when printing
java.util.Timer timer = new Timer(); //Used to control text speed
//java.util.TimerTask task;

private static volatile Textbox textbox = new Textbox();

public Textbox() {
    super(x, y);
    addLines();
}

public void draw(Graphics2D graphics2D) {
    this.graphics2D = graphics2D;
    this.graphics2D.drawImage(getImage(), x, y, null);
    if (!timerInitialized) {
        System.out.println("Scheduled..."); //For testing
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("Time's up!"); //For testing
                printChars(graphics2D, lines[lineNo]);
                timer.cancel();
            }
        }, 1000);
        timerInitialized = true;
    }
}

/*public void drawText(Image image, Point coordinates) {
    this.graphics2D.drawImage(image, coordinates.x, coordinates.y, null);
}*/

public Image getImage() {
    //graphics2D.drawString("Hello World", 100, 100); //Draws  a string
    ImageIcon imageIcon = new ImageIcon(
            "enterDirectoryHere"
                    + "\\src\\components\\Display\\Textbox.png");
    return imageIcon.getImage();
}

public void keyReleased(KeyEvent event) {
    int key = event.getKeyCode();

    if (key == KeyEvent.VK_ENTER) {
        if (GameFrame.screenPaused == true) {
            GameFrame.screenPaused = false;
        } else {
            GameFrame.screenPaused = true;
        }

    }
}

//FOR TESTING ONLY
public static void addLines() {
    lines = new String[] {"Hello", "World"};

}


/*
Make a boolean to indicate that line1 is full, and to continue on line 2 if
more text remains
Show cursor to indicate more text in lines
When pressing 'A' to continue text, translate text upward
If text exceeds boundaries, begin to cut off, starting from top, until gone

 */
/*public void printText(Graphics2D graphics2D) {
    if (lines != null) {
        //Assume that you already know the arrangement of words in the box
        //Starting point is 8, 112
        lineNo = 0;
        //endLine = false;
        while (lineNo < lines.length) {
            String line = lines[lineNo];
            if (line != null) {
                charNo = 0;
                for (int i = 0; i < line.length(); i++) {
                    printChars(graphics2D, line);
                }
            }
            lineNo++; //Move to the next line
            //line takes new line into account
            cx = 8;
        }
    }

}*/

public void printChars(Graphics2D graphics2D, String line) {
    if (charNo < line.length()) {
        if (lineNo == 0) {
            cy = 112;
        } else {
            cy = 128;
        }
        if (line.charAt(charNo) >= 'A' && line.charAt(charNo) <= 'Z') {
            Image image = getCharImage(line.charAt(charNo));
            graphics2D.drawImage(image, cx, cy, null);
            cx += image.getWidth(null);
        } else if (line.charAt(charNo) >= 'a' && line.charAt(charNo) <= 'z') {
            if (line.charAt(charNo) == 'b' || line.charAt(charNo) == 'd'
                    || line.charAt(charNo) == 'f' || line.charAt(charNo) == 'h'
                    || line.charAt(charNo) == 'k' || line.charAt(charNo) == 'l') {
                Image image = getCharImage(line.charAt(charNo));
                graphics2D.drawImage(image, cx, cy, null);
                cx += image.getWidth(null);
            } else if (line.charAt(charNo) == 'i' || line.charAt(charNo) == 'j'
                    || line.charAt(charNo) == 't') {
                cy += 1;
                //Add extra spaces for i, j, and l
                Image image = getCharImage(line.charAt(charNo));
                graphics2D.drawImage(image, cx, cy, null);
                cx += image.getWidth(null);
            } else {
                cy += 2;
                Image image = getCharImage(line.charAt(charNo));
                graphics2D.drawImage(image, cx, cy, null);
                cx += image.getWidth(null);
            }
        } else if (line.charAt(charNo) >= 32 && line.charAt(charNo) <= 95) {
            //Check for symbols and spaces
            if (line.charAt(charNo) == '_') {
                cx += 7;
            } else if (line.charAt(charNo) == '.') {
                cy += 5;
                Image image = getCharImage(line.charAt(charNo));
                graphics2D.drawImage(image, cx, cy, null);
                cx += image.getWidth(null);
            } else if (line.charAt(charNo) == ',') {

            } else if (line.charAt(charNo) == '/') {

            } else if (line.charAt(charNo) == '?') {

            } else if (line.charAt(charNo) == '!') {
                Image image = getCharImage(line.charAt(charNo));
                graphics2D.drawImage(image, cx, cy, null);
                cx += image.getWidth(null) + 8;
            } else if (line.charAt(charNo) == ']') {

            } else if (line.charAt(charNo) == '[') {

            } else if (line.charAt(charNo) == ':') {

            } else if (line.charAt(charNo) == ';') {

            } else if (line.charAt(charNo) == '-') {

            } else if (line.charAt(charNo) == '(') {

            } else if (line.charAt(charNo) == ')') {

            } else if (line.charAt(charNo) == '\'') {
                Image image = getCharImage(line.charAt(charNo));
                graphics2D.drawImage(image, cx, cy, null);
                cx += image.getWidth(null);
            }
        }
        cx += 2; //move two pixels to the right
        //Writes on the second half of the box if there is
        //more than 1 line
        if (lineNo == 0) {
            cy = 112;
        } else {
            cy = 128;
        }
        charNo++;
    } else {
        //charNo = 0;
        //lineNo++;
    }
    //Schedule the next letter here if there are more letters
    if (lineNo < lines.length || charNo < line.length()) {
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                printChars(graphics2D, lines[lineNo]);
                timer.cancel();
            }
        }, 200);
    }
}

GameFrame:

package components;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

public class GameFrame extends JPanel implements ActionListener{

javax.swing.Timer mainTimer;
Player player;
Textbox textbox;
Trainer trainer;
//static boolean showDialogueBox = true;
static boolean screenPaused = true;

static ArrayList<Trainer> trainerList = new ArrayList<>();

//Each setting has its own trainers

public GameFrame() {
    setFocusable(true);

    player = new Player();
    //player = new Player(138, 98); The bottom right corner
    //trainerList.add(trainer);
    textbox = new Textbox();
    addKeyListener(new KeyAdapt(player, textbox));
    mainTimer = new Timer(10, this); //Resets the screen every 10 millisecs
    mainTimer.start();
}

public void paint(Graphics graphics) {
    super.paint(graphics);
    Graphics2D graphics2D = (Graphics2D) graphics;
    //player.draw(graphics2D);
    if (screenPaused) {
        textbox.draw(graphics2D);
        //textbox.printText(graphics2D);
    }

}

@Override
public void actionPerformed(ActionEvent event) {
    player.update();
    repaint();
}

public static ArrayList<Trainer> getTrainerList() {
    return trainerList;
}

}

But I wind up with an empty box:See result here

When I comment out the portions where I set the timer, like this:

GameFrame:

package components;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

public class GameFrame extends JPanel implements ActionListener{

javax.swing.Timer mainTimer;
Player player;
Textbox textbox;
Trainer trainer;
//static boolean showDialogueBox = true;
static boolean screenPaused = true;

static ArrayList<Trainer> trainerList = new ArrayList<>();

//Each setting has its own trainers

public GameFrame() {
    setFocusable(true);

    player = new Player();
    //player = new Player(138, 98); The bottom right corner
    //trainerList.add(trainer);
    textbox = new Textbox();
    addKeyListener(new KeyAdapt(player, textbox));
    mainTimer = new Timer(10, this); //Resets the screen every 10 millisecs
    mainTimer.start();
}

public void paint(Graphics graphics) {
    super.paint(graphics);
    Graphics2D graphics2D = (Graphics2D) graphics;
    if (screenPaused) {
        textbox.draw(graphics2D);
        textbox.printText(graphics2D);
    }

}

@Override
public void actionPerformed(ActionEvent event) {
    player.update();
    repaint();
}

public static ArrayList<Trainer> getTrainerList() {
    return trainerList;
}

}

Textbox:

import java.awt.event.KeyEvent;
import java.util.Timer;
import java.util.TimerTask;

public class Textbox extends Entity {

private static String[] lines;

private static final int x = 1;
private static final int y = 97;
private Graphics2D graphics2D;
int lineNo = 0; //Used to count the line number when printing
int charNo = 0; //Used to count the character number when printing
int cx; //Used for the coordinates of each character printed
int cy; //Used for the coordinates of each character printed
boolean timerInitialized = false; //Used to indicate end of line when printing
java.util.Timer timer = new Timer();

private static volatile Textbox textbox = new Textbox();

public Textbox() {
    super(x, y);
    addLines();
}

public void draw(Graphics2D graphics2D) {
    this.graphics2D = graphics2D;
    this.graphics2D.drawImage(getImage(), x, y, null);
    if (!timerInitialized) {
        /*System.out.println("Scheduled..."); //For testing
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("Time's up!"); //For testing
                printChars(graphics2D, lines[lineNo]);
                timer.cancel();
            }
        }, 1000);*/
        timerInitialized = true;
    }
}

/*public void drawText(Image image, Point coordinates) {
    this.graphics2D.drawImage(image, coordinates.x, coordinates.y, null);
}*/

public Image getImage() {
    //graphics2D.drawString("Hello World", 100, 100); //Draws  a string
    ImageIcon imageIcon = new ImageIcon(
            "C:\\EnterDirectoryHere"
                    + "\\src\\components\\Display\\Textbox.png");
    return imageIcon.getImage();

public void keyReleased(KeyEvent event) {

    int key = event.getKeyCode();

    if (key == KeyEvent.VK_ENTER) {
        if (GameFrame.screenPaused == true) {
            GameFrame.screenPaused = false;
        } else {
            GameFrame.screenPaused = true;
        }

    }
}

//FOR TESTING ONLY
public static void addLines() {
    lines = new String[] {"Hello", "World"};

}


/*
Make a boolean to indicate that line1 is full, and to continue on line 2 if
more text remains
Show cursor to indicate more text in lines
When pressing 'A' to continue text, translate text upward
If text exceeds boundaries, begin to cut off, starting from top, until gone

 */
public void printText(Graphics2D graphics2D) {
    if (lines != null) {
        //Assume that you already know the arrangement of words in the box
        //Starting point is 8, 112
        lineNo = 0;
        //endLine = false;
        while (lineNo < lines.length) {
            String line = lines[lineNo];
            if (line != null) {
                charNo = 0;
                for (int i = 0; i < line.length(); i++) {
                    printChars(graphics2D, line);
                }
            }
            lineNo++; //Move to the next line
            //line takes new line into account
            cx = 8;
        }
    }

}

public void printChars(Graphics2D graphics2D, String line) {
    if (charNo < line.length()) {
        if (lineNo == 0) {
            cy = 112;
        } else {
            cy = 128;
        }
        if (line.charAt(charNo) >= 'A' && line.charAt(charNo) <= 'Z') {
            Image image = getCharImage(line.charAt(charNo));
            graphics2D.drawImage(image, cx, cy, null);
            cx += image.getWidth(null);
        } else if (line.charAt(charNo) >= 'a' && line.charAt(charNo) <= 'z') {
            if (line.charAt(charNo) == 'b' || line.charAt(charNo) == 'd'
                    || line.charAt(charNo) == 'f' || line.charAt(charNo) == 'h'
                    || line.charAt(charNo) == 'k' || line.charAt(charNo) == 'l') {
                Image image = getCharImage(line.charAt(charNo));
                graphics2D.drawImage(image, cx, cy, null);
                cx += image.getWidth(null);
            } else if (line.charAt(charNo) == 'i' || line.charAt(charNo) == 'j'
                    || line.charAt(charNo) == 't') {
                cy += 1;
                //Add extra spaces for i, j, and l
                Image image = getCharImage(line.charAt(charNo));
                graphics2D.drawImage(image, cx, cy, null);
                cx += image.getWidth(null);
            } else {
                cy += 2;
                Image image = getCharImage(line.charAt(charNo));
                graphics2D.drawImage(image, cx, cy, null);
                cx += image.getWidth(null);
            }
        } else if (line.charAt(charNo) >= 32 && line.charAt(charNo) <= 95) {
            //Check for symbols and spaces
            if (line.charAt(charNo) == '_') {
                cx += 7;
            } else if (line.charAt(charNo) == '.') {
                cy += 5;
                Image image = getCharImage(line.charAt(charNo));
                graphics2D.drawImage(image, cx, cy, null);
                cx += image.getWidth(null);
            } else if (line.charAt(charNo) == ',') {

            } else if (line.charAt(charNo) == '/') {

            } else if (line.charAt(charNo) == '?') {

            } else if (line.charAt(charNo) == '!') {
                Image image = getCharImage(line.charAt(charNo));
                graphics2D.drawImage(image, cx, cy, null);
                cx += image.getWidth(null) + 8;
            } else if (line.charAt(charNo) == ']') {

            } else if (line.charAt(charNo) == '[') {

            } else if (line.charAt(charNo) == ':') {

            } else if (line.charAt(charNo) == ';') {

            } else if (line.charAt(charNo) == '-') {

            } else if (line.charAt(charNo) == '(') {

            } else if (line.charAt(charNo) == ')') {

            } else if (line.charAt(charNo) == '\'') {
                Image image = getCharImage(line.charAt(charNo));
                graphics2D.drawImage(image, cx, cy, null);
                cx += image.getWidth(null);
            }
        }
        cx += 2; //move two pixels to the right
        //Writes on the second half of the box if there is
        //more than 1 line
        if (lineNo == 0) {
            cy = 112;
        } else {
            cy = 128;
        }
        charNo++;
    } else {
        //charNo = 0;
        //lineNo++;
    }
    //Schedule the next letter here if there are more letters
    if (lineNo < lines.length || charNo < line.length()) {
        /*timer.schedule(new TimerTask() {
            @Override
            public void run() {
                printChars(graphics2D, lines[lineNo]);
                timer.cancel();
            }
        }, 200);*/
    }
}

the text shows up fine, but it shows up all at once, which isn't what I want.See result here Am I forgetting to do something?

bds
  • 11
  • 1
  • 5
  • 1
    You have a "while loop". The GUI can't repaint itself until the loop is finished executing. The point of a Timer is to replace the while loop. Maybe this simple example: https://stackoverflow.com/a/33907282/131872 will help. – camickr Mar 24 '20 at 03:47
  • Are you referring to the loop in printText? If so, that method is not used in the first case. I commented out the code to reflect this. – bds Mar 24 '20 at 04:38
  • 1
    For better help sooner, [edit] to add a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). – Andrew Thompson Mar 24 '20 at 04:41
  • 1
    Yes, well you have all kinds of uncommented code everywhere so there is no way we can really tell what you are attempting to do. You have been given a simple working example of how a Timer works. I suggest you simplify your code so that you understand how to use a TImer and then add back in more complex logic. There is no way we can help with the posted code. – camickr Mar 24 '20 at 14:22

1 Answers1

0

I realized what the problem was. I wasn't updating the text to be displayed every time draw() got called. I was able to get the results I wanted by doing this:

public void draw(Graphics2D graphics2D) {
    graphics2D.drawImage(getImage(), x, y, null);
    //Every time draw is called, ensure that the coordinates are the same
    //each time text is redrawn
    if (!display.isEmpty()) { //This will only print when characters have
        //been added every second
        for (int i = 0; i < display.size(); i++) {
            drawText(graphics2D, display.get(i).charAt(0), coordinates.get(i));
        }
    }
    if (!timerInitialized && line1 != null) { //This only allows the timer to be set once
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                addTextToDisplay(lines[0]);
            }
        }, 100);
        timerInitialized = true;
    }
}

I used two arraylists, display and coordinates. Display lists the letters to be printed, and coordinates marks that character's coordinates on the screen.

bds
  • 11
  • 1
  • 5