Home > Enterprise >  How to constantly update a canvas with a string?
How to constantly update a canvas with a string?

Time:04-07

I'm attempting to make a simple game that displays the word that the user types as they type it. However, I'm unsure how I could recall or update the write() method in order to show the string currentWord as the user types it, each time a new character is added or deleted.

I'm not sure if this is the right way to go about this or not:

import java.awt.*;

import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JFrame;
import javax.swing.JButton;

import java.util.*;

public class CopyOfGamePanel extends Canvas {

    public static String currentWord = "BEGIN";

    public static void main(String[] args) {
        String[] acceptable = {
            "pressed A",
            "pressed B",
            "pressed C",
            "pressed D",
            "pressed E",
            "pressed F",
            "pressed G",
            "pressed H",
            "pressed I",
            "pressed J",
            "pressed K",
            "pressed L",
            "pressed M",
            "pressed N",
            "pressed O",
            "pressed P",
            "pressed Q",
            "pressed R",
            "pressed S",
            "pressed T",
            "pressed U",
            "pressed V",
            "pressed W",
            "pressed X",
            "pressed Y",
            "pressed Z"
        };

        JFrame frame = new JFrame();
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setFocusable(true);

        Canvas canvas = new CopyOfGamePanel();
        canvas.setSize(500, 700);
        canvas.setBackground(Color.white);
        frame.getContentPane().add(canvas);

        frame.pack();
        frame.setVisible(true);

        java.awt.KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new java.awt.KeyEventDispatcher() {
            public boolean dispatchKeyEvent(java.awt.event.KeyEvent event) {
                String key = javax.swing.KeyStroke.getKeyStrokeForEvent(event).toString();
                if (key.equals("pressed BACK_SPACE"))
                    deleteLetter();
                if (Arrays.asList(acceptable).contains(key)) {
                    addLetter(key);
                    frame.pack();
                }
                //System.out.println(key);
                return true;
            }
        });
    }
    public void paint(Graphics g) {
        backgroundGUI(g);
        write(g);
    }

    public void backgroundGUI(Graphics g) {

        g.drawLine(0, 300, 500, 300);

    }
    public void write(Graphics g) {

        g.drawString(currentWord, 50, 290);

    }


    public static void addLetter(String key) {
        char letter = key.charAt(8);

        currentWord = currentWord   letter;
        System.out.println("Current Word: "   currentWord);

    }
    public static void deleteLetter() {
        System.out.println("Delete a letter");
        if (currentWord.length() > 0) {
            currentWord = currentWord.substring(0, currentWord.length() - 1);
            System.out.println("Current Word: "   currentWord);
        } else {
            System.out.println("There are no more letters to delete");
        }
    }
}

CodePudding user response:

You're looking for Canvas#repaint to trigger a new paint cycle.

First, I'd isolate the keyboard input handling to the CopyOfGamePanel class itself, so it can do the update automatically. If you need input to go through some other workflow (for some strange reasons), then CopyOfGamePanel will need to be notified (probably via some kind of observer/listener callback) with the information it needs and repaint itself.

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.util.Arrays;
import javax.swing.JFrame;

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

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new CopyOfGamePanel());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class CopyOfGamePanel extends Canvas {

        public static String currentWord = "BEGIN";
        private String[] acceptable = {"pressed A", "pressed B", "pressed C", "pressed D", "pressed E", "pressed F", "pressed G",
            "pressed H", "pressed I", "pressed J", "pressed K", "pressed L", "pressed M", "pressed N", "pressed O",
            "pressed P", "pressed Q", "pressed R", "pressed S", "pressed T", "pressed U", "pressed V", "pressed W",
            "pressed X", "pressed Y", "pressed Z"};

        public CopyOfGamePanel() {
            setBackground(Color.WHITE);
            java.awt.KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new java.awt.KeyEventDispatcher() {
                public boolean dispatchKeyEvent(java.awt.event.KeyEvent event) {
                    String key = javax.swing.KeyStroke.getKeyStrokeForEvent(event).toString();
                    if (key.equals("pressed BACK_SPACE")) {
                        deleteLetter();
                    }
                    if (Arrays.asList(acceptable).contains(key)) {
                        addLetter(key);
                    }
                    return true;
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(500, 700);
        }

        public void paint(Graphics g) {
            backgroundGUI(g);
            write(g);
        }

        public void backgroundGUI(Graphics g) {
            g.drawLine(0, 300, 500, 300);
        }

        public void write(Graphics g) {
            g.drawString(currentWord, 50, 290);
        }

        public void addLetter(String key) {
            char letter = key.charAt(8);

            currentWord = currentWord   letter;
            System.out.println("Current Word: "   currentWord);
            repaint();
        }

        public void deleteLetter() {
            System.out.println("Delete a letter");
            if (currentWord.length() > 0) {
                currentWord = currentWord.substring(0, currentWord.length() - 1);
                System.out.println("Current Word: "   currentWord);
            } else {
                System.out.println("There are no more letters to delete");
            }
            repaint();
        }
    }

}

Questions pop up as to why:

  • You need to use Canvas for this, this is quite a "low level" component, so unless you're actually making use of BufferStrategy it seems like a waste (and a source of possible issues)
  • You're not using a JTextField (or if you're hell bent on AWT, TextField) to manage user input
  • You're not using KeyListener, no offence, but using KeyboardFocusManager like this is a lot like trying to crack a peanut with C4, sure, it'll probably work, but it's also likely to create a mess.

I think you might want to take a look at:

If you're just starting out with this kind of stuff, it might even be better to look at JavaFX

  • Related