所以我有一个GUI,一个Tile类和一个方法类。我在Game类中创建了四个图块,这些图块由图块组成,每个图块中都包含一个字母和一个颜色。现在,我想创建一个方法,当我单击键盘上的某个键到图块上该特定字母时,它将删除Tile。我该怎么办?是否在模型类中创建该方法并在Game(GUI)类中调用它?
首先,您的代码混乱不堪。您正在充分利用static它,但它不会帮助您。
static
例如,我对您的Tile课堂进行了重新设计,使其看起来更像这样。
Tile
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()); } }
而不是randomLetter每次调用getChar或时都调用convert它,只应在实际需要一个新字符时才使用它,否则您将永远不知道Tile字符的实际含义是/将要以什么开头。
randomLetter
getChar
convert
接下来,我们需要该模式的某种观察者契约,例如,它可以告诉我们什么时候发生了变化。
public interface ModelListener { public void tileWasRemoved(Tile tile); }
没什么特别的,但这提供了一种方法,可以在删除a和实际删除Modela时提供通知。Tile``Tile
Model
Tile``Tile
接下来,我对其进行了更新,Model以使其实际成为“模型”。在Model现在保持list的TileS和用于添加和删除它们提供的功能。它还为ModelListener和事件触发提供支持
list
ModelListener
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); } }
接下来,我转到Game并对其进行了更新,以便将Tiles 添加到Model并使用Model数据来设置UI。然后注册KeyListener和ModelListener
Game
KeyListener
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(); }
最后,该keyTyped事件现在要求Model删除Tile给定密钥中的一个…
keyTyped
@Override public void keyTyped(KeyEvent e) { model.removeByChar(e.getKeyChar()); }
作为概念证明…
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()); } } }
作为一般经验法则,KeyListener使用起来很麻烦,例如,您应该使用键绑定API
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()); } } }
有关更多详细信息,请参见如何使用键绑定。