So I have a GUI, a Tile class and a method class. I created four tiles in my Game class which consists of Tiles that has contains a letter and a color in each of them. I now wan
To start with, you code is in mess. You are making to much use of static
and it's not going to help you.
For example, I re-worked your Tile
class to look more like this.
public class Tile extends JLabel {
public static Font font = new Font("Serif", Font.BOLD, 39);
private char _c;
public Tile(char c, Color background) {
setBackground(background);
setOpaque(true);
_c = c;
setText(convert());
}
public static char randomLetter() {
Random r = new Random();
char randomChar = (char) (97 + r.nextInt(25));
return randomChar;
}
public char getChar() {
return _c;
}
public String convert() {
return String.valueOf(getChar());
}
}
Rather then calling randomLetter
each time you called getChar
or convert
, you should only be using it when you actually need a new character, otherwise you'll never know what the Tile
's character actually is/was to begin with
Next, we need some kind of observer contract for the mode, so it can tell us when things have changed, for example.
public interface ModelListener {
public void tileWasRemoved(Tile tile);
}
It's nothing special, but this provides a means for the Model
to provide notification when a Tile
is removed and which Tile
was actually removed.
Next, I updated the Model
so that it actual "models" something. The Model
now maintains a list
of Tile
s and provides functionality for adding and removing them. It also provides support for the ModelListener
and event triggering
public class Model {
private ArrayList<Tile> list = new ArrayList<Tile>();
private List<ModelListener> listeners = new ArrayList<>(25);
public Model() {
}
public void addModelListener(ModelListener listener) {
listeners.add(listener);
}
public void removeModelListener(ModelListener listener) {
listeners.remove(listener);
}
protected void fireTileRemoved(Tile tile) {
for (ModelListener listener : listeners) {
listener.tileWasRemoved(tile);
}
}
public void removeByChar(char value) {
Iterator<Tile> iterator = list.iterator();
while (iterator.hasNext()) {
Tile tile = iterator.next();
if (value == tile.getChar()) {
fireTileRemoved(tile);
iterator.remove();
}
}
}
private void add(Tile tile) {
list.add(tile);
}
private Iterable<Tile> getTiles() {
return Collections.unmodifiableList(list);
}
}
Next, I went to the Game
and updated it so it adds Tile
s to the Model
and uses the Model
data to setup the UI. It then registers the KeyListener
and ModelListener
public Game() {
model = new Model();
model.add(new Tile(Tile.randomLetter(), Color.WHITE));
model.add(new Tile(Tile.randomLetter(), Color.RED));
model.add(new Tile(Tile.randomLetter(), Color.GREEN));
model.add(new Tile(Tile.randomLetter(), Color.YELLOW));
JFrame frame = new JFrame();
frame.getContentPane().setLayout(new GridLayout(4, 1));
frame.setSize(500, 800);
frame.setVisible(true);
for (Tile tile : model.getTiles()) {
frame.add(tile);
}
model.addModelListener(new ModelListener() {
@Override
public void tileWasRemoved(Tile tile) {
frame.remove(tile);
frame.revalidate();
frame.repaint();
}
});
frame.getContentPane().addKeyListener(this);
frame.getContentPane().setFocusable(true);
frame.getContentPane().requestFocusInWindow();
}
And finally, the keyTyped
event now asks the Model
to remove a Tile
of the given key...
@Override
public void keyTyped(KeyEvent e) {
model.removeByChar(e.getKeyChar());
}
As a proof of concept...
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Game implements KeyListener {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
new Game();
}
});
}
private Model model;
public Game() {
model = new Model();
model.add(new Tile(Tile.randomLetter(), Color.WHITE));
model.add(new Tile(Tile.randomLetter(), Color.RED));
model.add(new Tile(Tile.randomLetter(), Color.GREEN));
model.add(new Tile(Tile.randomLetter(), Color.YELLOW));
JFrame frame = new JFrame();
frame.getContentPane().setLayout(new GridLayout(4, 1));
frame.setSize(500, 800);
frame.setVisible(true);
for (Tile tile : model.getTiles()) {
frame.add(tile);
}
model.addModelListener(new ModelListener() {
@Override
public void tileWasRemoved(Tile tile) {
frame.remove(tile);
frame.revalidate();
frame.repaint();
}
});
frame.getContentPane().addKeyListener(this);
frame.getContentPane().setFocusable(true);
frame.getContentPane().requestFocusInWindow();
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
model.removeByChar(e.getKeyChar());
}
public interface ModelListener {
public void tileWasRemoved(Tile tile);
}
public class Model {
private ArrayList<Tile> list = new ArrayList<Tile>();
private List<ModelListener> listeners = new ArrayList<>(25);
public Model() {
}
public void addModelListener(ModelListener listener) {
listeners.add(listener);
}
public void removeModelListener(ModelListener listener) {
listeners.remove(listener);
}
protected void fireTileRemoved(Tile tile) {
for (ModelListener listener : listeners) {
listener.tileWasRemoved(tile);
}
}
public void removeByChar(char value) {
Iterator<Tile> iterator = list.iterator();
while (iterator.hasNext()) {
Tile tile = iterator.next();
if (value == tile.getChar()) {
fireTileRemoved(tile);
iterator.remove();
}
}
}
private void add(Tile tile) {
list.add(tile);
}
private Iterable<Tile> getTiles() {
return Collections.unmodifiableList(list);
}
}
public static class Tile extends JLabel {
public static Font font = new Font("Serif", Font.BOLD, 39);
private char _c;
public Tile(char c, Color background) {
setBackground(background);
setOpaque(true);
_c = c;
setText(convert());
}
public static char randomLetter() {
Random r = new Random();
char randomChar = (char) (97 + r.nextInt(25));
return randomChar;
}
public char getChar() {
return _c;
}
public String convert() {
return String.valueOf(getChar());
}
}
}
As a general rule of thumb, KeyListener
is a pain to work with and you should be making use of the key bindings API instead, for example
import java.awt.AWTKeyStroke;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Game {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
new Game();
}
});
}
private Model model;
public Game() {
model = new Model();
model.add(new Tile(Tile.randomLetter(), Color.WHITE));
model.add(new Tile(Tile.randomLetter(), Color.RED));
model.add(new Tile(Tile.randomLetter(), Color.GREEN));
model.add(new Tile(Tile.randomLetter(), Color.YELLOW));
JFrame frame = new JFrame();
frame.getContentPane().setLayout(new GridLayout(4, 1));
frame.setSize(500, 800);
frame.setVisible(true);
for (Tile tile : model.getTiles()) {
frame.add(tile);
KeyStroke ks = KeyStroke.getKeyStroke(tile.getChar());
String name = "typed." + tile.getChar();
Action action = new TileAction(model, tile.getChar());
registerKeyBinding((JComponent)frame.getContentPane(), name, ks, action);
}
model.addModelListener(new ModelListener() {
@Override
public void tileWasRemoved(Tile tile) {
frame.remove(tile);
frame.revalidate();
frame.repaint();
}
});
}
public void registerKeyBinding(JComponent parent, String name, KeyStroke ks, Action action) {
InputMap im = parent.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
ActionMap am = parent.getActionMap();
im.put(ks, name);
am.put(name, action);
}
public class TileAction extends AbstractAction {
private Model model;
private char value;
public TileAction(Model model, char value) {
this.model = model;
this.value = value;
}
@Override
public void actionPerformed(ActionEvent e) {
model.removeByChar(value);
}
}
public interface ModelListener {
public void tileWasRemoved(Tile tile);
}
public class Model {
private ArrayList<Tile> list = new ArrayList<Tile>();
private List<ModelListener> listeners = new ArrayList<>(25);
public Model() {
}
public void addModelListener(ModelListener listener) {
listeners.add(listener);
}
public void removeModelListener(ModelListener listener) {
listeners.remove(listener);
}
protected void fireTileRemoved(Tile tile) {
for (ModelListener listener : listeners) {
listener.tileWasRemoved(tile);
}
}
public void removeByChar(char value) {
Iterator<Tile> iterator = list.iterator();
while (iterator.hasNext()) {
Tile tile = iterator.next();
if (value == tile.getChar()) {
fireTileRemoved(tile);
iterator.remove();
}
}
}
private void add(Tile tile) {
list.add(tile);
}
private Iterable<Tile> getTiles() {
return Collections.unmodifiableList(list);
}
}
public static class Tile extends JLabel {
public static Font font = new Font("Serif", Font.BOLD, 39);
private char _c;
public Tile(char c, Color background) {
setBackground(background);
setOpaque(true);
_c = c;
setText(convert());
}
public static char randomLetter() {
Random r = new Random();
char randomChar = (char) (97 + r.nextInt(25));
return randomChar;
}
public char getChar() {
return _c;
}
public String convert() {
return String.valueOf(getChar());
}
}
}
See How to Use Key Bindings for more details.